ink_storage_traits/layout/
impls.rs

1// Copyright (C) Use Ink (UK) Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::{
16    Packed,
17    StorageLayout,
18};
19use ink_metadata::layout::{
20    ArrayLayout,
21    Discriminant,
22    EnumLayout,
23    FieldLayout,
24    Layout,
25    LayoutKey,
26    LeafLayout,
27    StructLayout,
28};
29use ink_prelude::{
30    boxed::Box,
31    collections::{
32        BTreeMap,
33        BTreeSet,
34        VecDeque,
35    },
36    string::String,
37    vec::Vec,
38};
39use ink_primitives::{
40    AccountId,
41    Address,
42    Hash,
43    Key,
44    H256,
45    U256,
46};
47use scale_info::TypeInfo;
48
49macro_rules! impl_storage_layout_for_primitives {
50    ( $($name:ty),* $(,)? ) => {
51        $(
52            impl StorageLayout for $name {
53                fn layout(key: &Key) -> Layout {
54                    Layout::Leaf(LeafLayout::from_key::<$name>(LayoutKey::from(key)))
55                }
56            }
57        )*
58    };
59}
60#[rustfmt::skip]
61impl_storage_layout_for_primitives!(
62    AccountId, Address, Hash, String,
63    H256, U256,
64    bool, char, (),
65    u8, u16, u32, u64, u128,
66    i8, i16, i32, i64, i128,
67);
68
69macro_rules! impl_layout_for_tuple {
70    ( $(($frag:ident, $id:literal)),* $(,)? ) => {
71        const _: () = {
72            // The name of the tuple looks like `(A)`, `(A, B)` ... `(A, B, ..., J)`
73            const TUPLE_NAME: &'static str = stringify!(($($frag),*));
74
75            impl<$($frag),*> StorageLayout for ($($frag),* ,)
76            where
77                $(
78                    $frag: StorageLayout,
79                )*
80            {
81                fn layout(key: &Key) -> Layout {
82                    Layout::Struct(
83                        StructLayout::new(
84                            TUPLE_NAME,
85                            [
86                                $(
87                                    FieldLayout::new(
88                                        ::core::stringify!($id),
89                                        <$frag as StorageLayout>::layout(key)
90                                    ),
91                                )*
92                            ]
93                        )
94                    )
95                }
96            }
97        };
98    }
99}
100
101impl_layout_for_tuple!((A, 0));
102impl_layout_for_tuple!((A, 0), (B, 1));
103impl_layout_for_tuple!((A, 0), (B, 1), (C, 2));
104impl_layout_for_tuple!((A, 0), (B, 1), (C, 2), (D, 3));
105impl_layout_for_tuple!((A, 0), (B, 1), (C, 2), (D, 3), (E, 4));
106impl_layout_for_tuple!((A, 0), (B, 1), (C, 2), (D, 3), (E, 4), (F, 5));
107impl_layout_for_tuple!((A, 0), (B, 1), (C, 2), (D, 3), (E, 4), (F, 5), (G, 6));
108impl_layout_for_tuple!(
109    (A, 0),
110    (B, 1),
111    (C, 2),
112    (D, 3),
113    (E, 4),
114    (F, 5),
115    (G, 6),
116    (H, 7)
117);
118impl_layout_for_tuple!(
119    (A, 0),
120    (B, 1),
121    (C, 2),
122    (D, 3),
123    (E, 4),
124    (F, 5),
125    (G, 6),
126    (H, 7),
127    (I, 8)
128);
129impl_layout_for_tuple!(
130    (A, 0),
131    (B, 1),
132    (C, 2),
133    (D, 3),
134    (E, 4),
135    (F, 5),
136    (G, 6),
137    (H, 7),
138    (I, 8),
139    (J, 9)
140);
141
142impl<T, const N: usize> StorageLayout for [T; N]
143where
144    T: StorageLayout + Packed,
145{
146    fn layout(key: &Key) -> Layout {
147        let len: u32 = N as u32;
148        // Generic type is packed, so it doesn't take any cell
149        Layout::Array(ArrayLayout::new(
150            LayoutKey::from(key),
151            len,
152            <T as StorageLayout>::layout(key),
153        ))
154    }
155}
156
157impl<T> StorageLayout for Box<T>
158where
159    T: StorageLayout,
160{
161    fn layout(key: &Key) -> Layout {
162        <T as StorageLayout>::layout(key)
163    }
164}
165
166impl<T> StorageLayout for Option<T>
167where
168    T: StorageLayout,
169{
170    fn layout(key: &Key) -> Layout {
171        Layout::Enum(EnumLayout::new(
172            "Option",
173            key,
174            [
175                (Discriminant::from(0), StructLayout::new("None", Vec::new())),
176                (
177                    Discriminant::from(1),
178                    StructLayout::new(
179                        "Some",
180                        [FieldLayout::new("0", <T as StorageLayout>::layout(key))],
181                    ),
182                ),
183            ],
184        ))
185    }
186}
187
188impl<T, E> StorageLayout for Result<T, E>
189where
190    T: StorageLayout,
191    E: StorageLayout,
192{
193    fn layout(key: &Key) -> Layout {
194        Layout::Enum(EnumLayout::new(
195            "Result",
196            *key,
197            [
198                (
199                    Discriminant::from(0),
200                    StructLayout::new(
201                        "Ok",
202                        [FieldLayout::new("0", <T as StorageLayout>::layout(key))],
203                    ),
204                ),
205                (
206                    Discriminant::from(1),
207                    StructLayout::new(
208                        "Err",
209                        [FieldLayout::new("1", <E as StorageLayout>::layout(key))],
210                    ),
211                ),
212            ],
213        ))
214    }
215}
216
217impl<T> StorageLayout for Vec<T>
218where
219    T: TypeInfo + 'static + Packed,
220{
221    fn layout(key: &Key) -> Layout {
222        Layout::Leaf(LeafLayout::from_key::<Self>(LayoutKey::from(key)))
223    }
224}
225
226impl<K, V> StorageLayout for BTreeMap<K, V>
227where
228    K: TypeInfo + 'static + Packed,
229    V: TypeInfo + 'static + Packed,
230{
231    fn layout(key: &Key) -> Layout {
232        Layout::Leaf(LeafLayout::from_key::<Self>(LayoutKey::from(key)))
233    }
234}
235
236impl<T> StorageLayout for BTreeSet<T>
237where
238    T: TypeInfo + 'static + Packed,
239{
240    fn layout(key: &Key) -> Layout {
241        Layout::Leaf(LeafLayout::from_key::<Self>(LayoutKey::from(key)))
242    }
243}
244
245impl<T> StorageLayout for VecDeque<T>
246where
247    T: TypeInfo + 'static + Packed,
248{
249    fn layout(key: &Key) -> Layout {
250        Layout::Leaf(LeafLayout::from_key::<Self>(LayoutKey::from(key)))
251    }
252}