1use alloc::vec::Vec;
17use scale_type_resolver::TypeResolver;
18
19pub trait IntoEncodableValues {
24 type Values<'this>: EncodableValues
26 where
27 Self: 'this;
28 #[allow(clippy::wrong_self_convention)]
33 fn into_encodable_values(&self) -> Self::Values<'_>;
34 fn num_encodable_values(&self) -> usize;
36}
37
38pub trait EncodableValues {
41 fn encode_next_value_to<Resolver>(
49 &mut self,
50 type_id: Resolver::TypeId,
51 types: &Resolver,
52 out: &mut Vec<u8>,
53 ) -> Result<(), scale_encode::Error>
54 where
55 Resolver: TypeResolver;
56
57 fn encode_next_value<Resolver>(
65 &mut self,
66 type_id: Resolver::TypeId,
67 types: &Resolver,
68 ) -> Result<Vec<u8>, scale_encode::Error>
69 where
70 Resolver: TypeResolver,
71 {
72 let mut out = Vec::new();
73 self.encode_next_value_to(type_id, types, &mut out)
74 .map(|_| out)
75 }
76}
77
78impl<'a, T: IntoEncodableValues> IntoEncodableValues for &'a T {
80 type Values<'this>
81 = T::Values<'this>
82 where
83 'a: 'this;
84
85 fn into_encodable_values(&self) -> Self::Values<'_> {
86 (*self).into_encodable_values()
87 }
88 fn num_encodable_values(&self) -> usize {
89 (*self).num_encodable_values()
90 }
91}
92
93impl<K: scale_encode::EncodeAsType> IntoEncodableValues for Vec<K> {
95 type Values<'this>
96 = core::slice::Iter<'this, K>
97 where
98 K: 'this;
99 fn num_encodable_values(&self) -> usize {
100 self.len()
101 }
102 fn into_encodable_values(&self) -> Self::Values<'_> {
103 self.iter()
104 }
105}
106
107impl<'a, K: scale_encode::EncodeAsType> EncodableValues for core::slice::Iter<'a, K> {
108 fn encode_next_value_to<Resolver>(
109 &mut self,
110 type_id: Resolver::TypeId,
111 types: &Resolver,
112 out: &mut Vec<u8>,
113 ) -> Result<(), scale_encode::Error>
114 where
115 Resolver: TypeResolver,
116 {
117 let Some(next_key) = self.next() else {
118 return Err(scale_encode::Error::custom_str(
119 "encode_next_value_to called but no more values to encode",
120 ));
121 };
122 next_key.encode_as_type_to(type_id, types, out)
123 }
124}
125
126impl<K: scale_encode::EncodeAsType, const N: usize> IntoEncodableValues for [K; N] {
128 type Values<'this>
129 = core::slice::Iter<'this, K>
130 where
131 K: 'this;
132 fn num_encodable_values(&self) -> usize {
133 N
134 }
135 fn into_encodable_values(&self) -> Self::Values<'_> {
136 self.iter()
137 }
138}
139
140impl IntoEncodableValues for () {
142 type Values<'this> = ();
143 fn num_encodable_values(&self) -> usize {
144 0
145 }
146 fn into_encodable_values(&self) -> Self::Values<'_> {}
147}
148
149impl EncodableValues for () {
150 fn encode_next_value_to<Resolver>(
151 &mut self,
152 _type_id: Resolver::TypeId,
153 _types: &Resolver,
154 _out: &mut Vec<u8>,
155 ) -> Result<(), scale_encode::Error>
156 where
157 Resolver: TypeResolver,
158 {
159 Err(scale_encode::Error::custom_str(
160 "encode_next_value_to called on an empty tuple",
161 ))
162 }
163}
164
165macro_rules! impl_tuple_encodable {
167 ($($ty:ident $number:tt),*) => {
168 const _: () = {
169 const TUPLE_LEN: usize = 0 $(+ $number - $number + 1)*;
170 type TupleOf<$($ty),*> = ($($ty,)*);
171
172 impl <$($ty: scale_encode::EncodeAsType),*> IntoEncodableValues for TupleOf<$($ty),*> {
173 type Values<'this> = TupleIter<'this, TupleOf<$($ty),*>> where TupleOf<$($ty),*>: 'this;
174 fn num_encodable_values(&self) -> usize {
175 TUPLE_LEN
176 }
177 fn into_encodable_values(&self) -> Self::Values<'_> {
178 TupleIter {
179 idx: 0,
180 items: self,
181 }
182 }
183 }
184
185 pub struct TupleIter<'this, TupleTy> {
186 idx: usize,
187 items: &'this TupleTy
188 }
189
190 impl <'a, $($ty: scale_encode::EncodeAsType),*> EncodableValues for TupleIter<'a, TupleOf<$($ty),*>> {
191 fn encode_next_value_to<Resolver>(&mut self, type_id: Resolver::TypeId, types: &Resolver, out: &mut Vec<u8>) -> Result<(), scale_encode::Error>
192 where
193 Resolver: TypeResolver,
194 {
195 $(
196 if self.idx == $number {
197 let item = &self.items.$number;
198 item.encode_as_type_to(type_id, types, out)?;
199 self.idx += 1;
200 return Ok(());
201 }
202 )*
203 Err(scale_encode::Error::custom_str("encode_next_value_to called but no more tuple entries to encode"))
204 }
205 }
206 };
207 };
208}
209
210impl_tuple_encodable!(A 0);
211impl_tuple_encodable!(A 0, B 1);
212impl_tuple_encodable!(A 0, B 1, C 2);
213impl_tuple_encodable!(A 0, B 1, C 2, D 3);
214impl_tuple_encodable!(A 0, B 1, C 2, D 3, E 4);
215impl_tuple_encodable!(A 0, B 1, C 2, D 3, E 4, F 5);
216impl_tuple_encodable!(A 0, B 1, C 2, D 3, E 4, F 5, G 6);
217impl_tuple_encodable!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7);
218impl_tuple_encodable!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8);
219impl_tuple_encodable!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9);
220impl_tuple_encodable!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10);
221impl_tuple_encodable!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10, L 11);
222
223#[cfg(test)]
224mod test {
225 use super::*;
226 use parity_scale_codec::Encode;
227 use scale_info_legacy::LookupName;
228
229 fn ln(ty: &str) -> LookupName {
230 LookupName::parse(ty).unwrap()
231 }
232
233 #[test]
234 fn test_tuple_encodable_values() {
235 let types = crate::legacy_types::polkadot::relay_chain();
237 let types = types.for_spec_version(0);
238
239 let keys = (123u16, true, "hello");
240 assert_eq!(keys.num_encodable_values(), 3);
241 let mut encodable_values = keys.into_encodable_values();
242
243 let val = encodable_values
244 .encode_next_value(ln("u64"), &types)
245 .unwrap();
246 assert_eq!(val, 123u64.encode());
247
248 let val = encodable_values
249 .encode_next_value(ln("bool"), &types)
250 .unwrap();
251 assert_eq!(val, true.encode());
252
253 let val = encodable_values
254 .encode_next_value(ln("String"), &types)
255 .unwrap();
256 assert_eq!(val, "hello".encode());
257
258 assert!(
260 encodable_values
261 .encode_next_value(ln("foo"), &types)
262 .is_err()
263 );
264 assert!(
265 encodable_values
266 .encode_next_value(ln("foo"), &types)
267 .is_err()
268 );
269 }
270
271 #[test]
272 fn test_vec_encodable_values() {
273 let types = crate::legacy_types::polkadot::relay_chain();
275 let types = types.for_spec_version(0);
276
277 let keys = vec![123u16, 456u16, 789u16];
278 assert_eq!(keys.num_encodable_values(), 3);
279 let mut encodable_values = keys.into_encodable_values();
280
281 let val = encodable_values
282 .encode_next_value(ln("u64"), &types)
283 .unwrap();
284 assert_eq!(val, 123u64.encode());
285
286 let val = encodable_values
287 .encode_next_value(ln("u16"), &types)
288 .unwrap();
289 assert_eq!(val, 456u16.encode());
290
291 let val = encodable_values
292 .encode_next_value(ln("u32"), &types)
293 .unwrap();
294 assert_eq!(val, 789u32.encode());
295
296 assert!(
298 encodable_values
299 .encode_next_value(ln("foo"), &types)
300 .is_err()
301 );
302 assert!(
303 encodable_values
304 .encode_next_value(ln("foo"), &types)
305 .is_err()
306 );
307 }
308
309 #[test]
310 fn test_array_encodable_values() {
311 let types = crate::legacy_types::polkadot::relay_chain();
313 let types = types.for_spec_version(0);
314
315 let keys: [u16; 3] = [123, 456, 789];
316 assert_eq!(keys.num_encodable_values(), 3);
317 let mut encodable_values = keys.into_encodable_values();
318
319 let val = encodable_values
320 .encode_next_value(ln("u64"), &types)
321 .unwrap();
322 assert_eq!(val, 123u64.encode());
323
324 let val = encodable_values
325 .encode_next_value(ln("u16"), &types)
326 .unwrap();
327 assert_eq!(val, 456u16.encode());
328
329 let val = encodable_values
330 .encode_next_value(ln("u32"), &types)
331 .unwrap();
332 assert_eq!(val, 789u32.encode());
333
334 assert!(
336 encodable_values
337 .encode_next_value(ln("foo"), &types)
338 .is_err()
339 );
340 assert!(
341 encodable_values
342 .encode_next_value(ln("foo"), &types)
343 .is_err()
344 );
345 }
346}