Skip to content

Commit de6a3e0

Browse files
committed
codegen: Use packed arg for ink! storage_item
1 parent a979334 commit de6a3e0

File tree

2 files changed

+108
-48
lines changed

2 files changed

+108
-48
lines changed

crates/ink/codegen/src/generator/storage_item.rs

Lines changed: 67 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,16 @@ impl GenerateCode for StorageItem<'_> {
5353
Data::Union(union_item) => self.generate_union(union_item),
5454
};
5555

56-
let mut derive = quote! {};
57-
if self.item.config().derive() {
58-
derive = quote! {
56+
let config = self.item.config();
57+
let derive = if config.packed() {
58+
quote! {
59+
#[cfg_attr(feature = "std", derive(
60+
::ink::storage::traits::StorageLayout,
61+
))]
62+
#[ink::scale_derive(Encode, Decode, TypeInfo)]
63+
}
64+
} else if config.derive() {
65+
quote! {
5966
#[cfg_attr(feature = "std", derive(
6067
::ink::storage::traits::StorageLayout,
6168
))]
@@ -65,10 +72,16 @@ impl GenerateCode for StorageItem<'_> {
6572
::ink::storage::traits::StorageKey,
6673
::ink::storage::traits::Storable,
6774
)]
68-
};
69-
}
75+
}
76+
} else {
77+
quote! {}
78+
};
7079

71-
let type_check = self.generate_type_check();
80+
let type_check = if self.item.config().packed() {
81+
quote! {}
82+
} else {
83+
self.generate_type_check()
84+
};
7285

7386
quote! {
7487
#type_check
@@ -88,22 +101,32 @@ impl StorageItem<'_> {
88101
let generics = item.generics();
89102
let salt = item.salt();
90103

91-
let fields = struct_item.fields.iter().enumerate().map(|(i, field)| {
92-
convert_into_storage_field(struct_ident, None, &salt, i, field)
93-
});
104+
let fields = if self.item.config().packed() {
105+
let fields = struct_item.fields.iter();
106+
quote! {
107+
#(#fields),*
108+
}
109+
} else {
110+
let fields = struct_item.fields.iter().enumerate().map(|(i, field)| {
111+
convert_into_storage_field(struct_ident, None, &salt, i, field)
112+
});
113+
quote! {
114+
#(#fields),*
115+
}
116+
};
94117

95118
match struct_item.fields {
96119
Fields::Unnamed(_) => {
97120
quote! {
98121
#vis struct #struct_ident #generics (
99-
#(#fields),*
122+
#fields
100123
);
101124
}
102125
}
103126
_ => {
104127
quote! {
105128
#vis struct #struct_ident #generics {
106-
#(#fields),*
129+
#fields
107130
}
108131
}
109132
}
@@ -126,24 +149,29 @@ impl StorageItem<'_> {
126149
quote! {}
127150
};
128151

129-
let fields: Vec<_> = variant
130-
.fields
131-
.iter()
132-
.enumerate()
133-
.map(|(i, field)| {
152+
let fields = if self.item.config().packed() {
153+
let fields = variant.fields.iter();
154+
quote! {
155+
#(#fields),*
156+
}
157+
} else {
158+
let fields = variant.fields.iter().enumerate().map(|(i, field)| {
134159
convert_into_storage_field(
135160
enum_ident,
136161
Some(variant_ident),
137162
&salt,
138163
i,
139164
field,
140165
)
141-
})
142-
.collect();
166+
});
167+
quote! {
168+
#(#fields),*
169+
}
170+
};
143171

144172
let fields = match variant.fields {
145-
Fields::Named(_) => quote! { { #(#fields),* } },
146-
Fields::Unnamed(_) => quote! { ( #(#fields),* ) },
173+
Fields::Named(_) => quote! { { #fields } },
174+
Fields::Unnamed(_) => quote! { ( #fields ) },
147175
Fields::Unit => quote! {},
148176
};
149177

@@ -167,18 +195,28 @@ impl StorageItem<'_> {
167195
let generics = item.generics();
168196
let salt = item.salt();
169197

170-
let fields = union_item
171-
.fields
172-
.named
173-
.iter()
174-
.enumerate()
175-
.map(|(i, field)| {
176-
convert_into_storage_field(union_ident, None, &salt, i, field)
177-
});
198+
let fields = if self.item.config().packed() {
199+
let fields = union_item.fields.named.iter();
200+
quote! {
201+
#(#fields),*
202+
}
203+
} else {
204+
let fields = union_item
205+
.fields
206+
.named
207+
.iter()
208+
.enumerate()
209+
.map(|(i, field)| {
210+
convert_into_storage_field(union_ident, None, &salt, i, field)
211+
});
212+
quote! {
213+
#(#fields),*
214+
}
215+
};
178216

179217
quote! {
180218
#vis union #union_ident #generics {
181-
#(#fields),*
219+
#fields
182220
}
183221
}
184222
}

crates/ink/macro/src/lib.rs

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -897,13 +897,8 @@ pub fn event(attr: TokenStream, item: TokenStream) -> TokenStream {
897897
/// };
898898
/// use ink::storage::traits::Storable;
899899
///
900-
/// // Deriving `scale::Decode` and `scale::Encode` also derives blanket implementation of all
901-
/// // required traits to be storable.
902-
/// #[derive(scale::Decode, scale::Encode)]
903-
/// #[cfg_attr(
904-
/// feature = "std",
905-
/// derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout)
906-
/// )]
900+
/// // Example of how to define a packed type.
901+
/// #[ink::storage_item(packed)]
907902
/// #[derive(Default, Debug)]
908903
/// struct Packed {
909904
/// s1: u128,
@@ -912,12 +907,8 @@ pub fn event(attr: TokenStream, item: TokenStream) -> TokenStream {
912907
/// // s3: Vec<NonPacked>,
913908
/// }
914909
///
915-
/// // Example of how to define the packed type with generic.
916-
/// #[derive(scale::Decode, scale::Encode)]
917-
/// #[cfg_attr(
918-
/// feature = "std",
919-
/// derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout)
920-
/// )]
910+
/// // Example of how to define the packed type with generics.
911+
/// #[ink::storage_item(packed)]
921912
/// #[derive(Default, Debug)]
922913
/// struct PackedGeneric<T: ink::storage::traits::Packed> {
923914
/// s1: (u128, bool),
@@ -926,6 +917,8 @@ pub fn event(attr: TokenStream, item: TokenStream) -> TokenStream {
926917
/// }
927918
///
928919
/// // Example of how to define the non-packed type.
920+
/// // Note: `packed` argument defaults to `false`, so it can be omitted for non-packed types,
921+
/// // so the definition below is equivalent to `#[ink::storage_item(packed = false)]`.
929922
/// #[ink::storage_item]
930923
/// #[derive(Default, Debug)]
931924
/// struct NonPacked {
@@ -934,14 +927,27 @@ pub fn event(attr: TokenStream, item: TokenStream) -> TokenStream {
934927
/// }
935928
///
936929
/// // Example of how to define the non-packed generic type.
930+
/// #[ink::storage_item]
931+
/// #[derive(Default, Debug)]
932+
/// struct NonPackedGeneric<T>
933+
/// where
934+
/// T: Default + core::fmt::Debug,
935+
/// T: ink::storage::traits::Packed,
936+
/// {
937+
/// s1: u32,
938+
/// s2: T,
939+
/// s3: Mapping<u128, T>,
940+
/// }
941+
///
942+
/// // Example of how to define the non-packed generic type with manually derived storage traits.
937943
/// #[ink::storage_item(derive = false)]
938944
/// #[derive(Storable, StorableHint, StorageKey)]
939945
/// #[cfg_attr(
940946
/// feature = "std",
941947
/// derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout)
942948
/// )]
943949
/// #[derive(Default, Debug)]
944-
/// struct NonPackedGeneric<T>
950+
/// struct NonPackedGenericManual<T>
945951
/// where
946952
/// T: Default + core::fmt::Debug,
947953
/// T: ink::storage::traits::Packed,
@@ -952,11 +958,7 @@ pub fn event(attr: TokenStream, item: TokenStream) -> TokenStream {
952958
/// }
953959
///
954960
/// // Example of how to define a complex packed type.
955-
/// #[derive(scale::Decode, scale::Encode)]
956-
/// #[cfg_attr(
957-
/// feature = "std",
958-
/// derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout)
959-
/// )]
961+
/// #[ink::storage_item(packed)]
960962
/// #[derive(Default, Debug)]
961963
/// struct PackedComplex {
962964
/// s1: u128,
@@ -985,6 +987,26 @@ pub fn event(attr: TokenStream, item: TokenStream) -> TokenStream {
985987
/// The `#[ink::storage_item]` macro can be provided with an additional comma-separated
986988
/// header argument:
987989
///
990+
/// - `packed: flag`
991+
///
992+
/// Storage items flagged as `packed` use "packed" layout .
993+
///
994+
/// **Usage Example:**
995+
/// ```
996+
/// use ink::storage::Mapping;
997+
///
998+
/// #[ink::storage_item(packed)]
999+
/// struct PackedGeneric<T: ink::storage::traits::Packed> {
1000+
/// s1: (u128, bool),
1001+
/// s2: Vec<T>,
1002+
/// s3: String,
1003+
/// }
1004+
/// ```
1005+
///
1006+
/// **Default value:** not set.
1007+
/// **Note**: The default behavior is to use "non-packed" layout, and automatically
1008+
/// derive storage keys for each field.
1009+
///
9881010
/// - `derive: bool`
9891011
///
9901012
/// The `derive` configuration parameter is used to enable/disable auto deriving of

0 commit comments

Comments
 (0)