1#[cfg(feature = "bits")]
17mod bits;
18mod composite;
19#[cfg(feature = "primitive-types")]
20mod primitive_types;
21mod variant;
22
23use crate::{
24 error::{Error, ErrorKind, Kind},
25 EncodeAsFields, EncodeAsType,
26};
27use alloc::{
28 borrow::ToOwned,
29 boxed::Box,
30 collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque},
31 format,
32 rc::Rc,
33 string::{String, ToString},
34 sync::Arc,
35 vec::Vec,
36};
37use codec::{Compact, Encode};
38use core::{
39 marker::PhantomData,
40 num::{
41 NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroU128, NonZeroU16,
42 NonZeroU32, NonZeroU64, NonZeroU8,
43 },
44 ops::{Range, RangeInclusive},
45 time::Duration,
46};
47use scale_type_resolver::{visitor, FieldIter, Primitive, ResolvedTypeVisitor, TypeResolver};
48
49pub use composite::{Composite, CompositeField};
52pub use variant::Variant;
53
54fn resolve_type_and_encode<
55 'resolver,
56 R: TypeResolver,
57 V: ResolvedTypeVisitor<'resolver, TypeId = R::TypeId, Value = Result<(), Error>>,
58>(
59 types: &'resolver R,
60 type_id: R::TypeId,
61 visitor: V,
62) -> Result<(), Error> {
63 match types.resolve_type(type_id, visitor) {
64 Ok(res) => res,
65 Err(e) => Err(Error::new(ErrorKind::TypeResolvingError(e.to_string()))),
66 }
67}
68
69impl EncodeAsType for bool {
70 fn encode_as_type_to<R: TypeResolver>(
71 &self,
72 type_id: R::TypeId,
73 types: &R,
74 out: &mut Vec<u8>,
75 ) -> Result<(), Error> {
76 let type_id = find_single_entry_with_same_repr(type_id, types);
77
78 let wrong_shape_err = |type_id| {
79 Error::new(ErrorKind::WrongShape {
80 actual: Kind::Bool,
81 expected_id: format!("{type_id:?}"),
82 })
83 };
84
85 let v = visitor::new(type_id.clone(), |type_id, _| Err(wrong_shape_err(type_id)))
86 .visit_primitive(|type_id, primitive| {
87 if primitive == Primitive::Bool {
88 self.encode_to(out);
89 Ok(())
90 } else {
91 Err(wrong_shape_err(type_id))
92 }
93 })
94 .visit_not_found(|type_id| {
95 Err(Error::new(ErrorKind::TypeNotFound(format!("{type_id:?}"))))
96 });
97
98 resolve_type_and_encode(types, type_id, v)
99 }
100}
101
102impl EncodeAsType for str {
103 fn encode_as_type_to<R: TypeResolver>(
104 &self,
105 type_id: R::TypeId,
106 types: &R,
107 out: &mut Vec<u8>,
108 ) -> Result<(), Error> {
109 let type_id = find_single_entry_with_same_repr(type_id, types);
110
111 let wrong_shape_err = |type_id| {
112 Error::new(ErrorKind::WrongShape {
113 actual: Kind::Str,
114 expected_id: format!("{type_id:?}"),
115 })
116 };
117
118 let v = visitor::new(type_id.clone(), |type_id, _| Err(wrong_shape_err(type_id)))
119 .visit_primitive(|type_id, primitive| {
120 if primitive == Primitive::Str {
121 self.encode_to(out);
122 Ok(())
123 } else {
124 Err(wrong_shape_err(type_id))
125 }
126 })
127 .visit_not_found(|type_id| {
128 Err(Error::new(ErrorKind::TypeNotFound(format!("{type_id:?}"))))
129 });
130
131 resolve_type_and_encode(types, type_id, v)
132 }
133}
134
135impl<T> EncodeAsType for &T
136where
137 T: EncodeAsType + ?Sized,
138{
139 fn encode_as_type_to<R: TypeResolver>(
140 &self,
141 type_id: R::TypeId,
142 types: &R,
143 out: &mut Vec<u8>,
144 ) -> Result<(), Error> {
145 (*self).encode_as_type_to(type_id, types, out)
146 }
147}
148
149impl<'a, T> EncodeAsType for alloc::borrow::Cow<'a, T>
150where
151 T: 'a + EncodeAsType + ToOwned + ?Sized,
152{
153 fn encode_as_type_to<R: TypeResolver>(
154 &self,
155 type_id: R::TypeId,
156 types: &R,
157 out: &mut Vec<u8>,
158 ) -> Result<(), Error> {
159 (**self).encode_as_type_to(type_id, types, out)
160 }
161}
162
163impl<T> EncodeAsType for [T]
164where
165 T: EncodeAsType,
166{
167 fn encode_as_type_to<R: TypeResolver>(
168 &self,
169 type_id: R::TypeId,
170 types: &R,
171 out: &mut Vec<u8>,
172 ) -> Result<(), Error> {
173 encode_iterable_sequence_to(self.len(), self.iter(), type_id, types, out)
174 }
175}
176
177impl<const N: usize, T: EncodeAsType> EncodeAsType for [T; N] {
178 fn encode_as_type_to<R: TypeResolver>(
179 &self,
180 type_id: R::TypeId,
181 types: &R,
182 out: &mut Vec<u8>,
183 ) -> Result<(), Error> {
184 self[..].encode_as_type_to(type_id, types, out)
185 }
186}
187
188impl<T> EncodeAsType for PhantomData<T> {
189 fn encode_as_type_to<R: TypeResolver>(
190 &self,
191 type_id: R::TypeId,
192 types: &R,
193 out: &mut Vec<u8>,
194 ) -> Result<(), Error> {
195 ().encode_as_type_to(type_id, types, out)
196 }
197}
198
199impl<T: EncodeAsType, E: EncodeAsType> EncodeAsType for Result<T, E> {
200 fn encode_as_type_to<R: TypeResolver>(
201 &self,
202 type_id: R::TypeId,
203 types: &R,
204 out: &mut Vec<u8>,
205 ) -> Result<(), Error> {
206 match self {
207 Ok(v) => Variant {
208 name: "Ok",
209 fields: Composite::new([(None, CompositeField::new(v))].iter().copied()),
210 }
211 .encode_variant_as_type_to(type_id, types, out),
212 Err(e) => Variant {
213 name: "Err",
214 fields: Composite::new([(None, CompositeField::new(e))].iter().copied()),
215 }
216 .encode_variant_as_type_to(type_id, types, out),
217 }
218 }
219}
220
221impl<T: EncodeAsType> EncodeAsType for Option<T> {
222 fn encode_as_type_to<R: TypeResolver>(
223 &self,
224 type_id: R::TypeId,
225 types: &R,
226 out: &mut Vec<u8>,
227 ) -> Result<(), Error> {
228 match self {
229 Some(v) => Variant {
230 name: "Some",
231 fields: Composite::new([(None, CompositeField::new(v))].iter().copied()),
232 }
233 .encode_variant_as_type_to(type_id, types, out),
234 None => Variant {
235 name: "None",
236 fields: Composite::new([].iter().copied()),
237 }
238 .encode_variant_as_type_to(type_id, types, out),
239 }
240 }
241}
242
243macro_rules! impl_encode_number {
245 ($ty:ty) => {
246 impl EncodeAsType for $ty {
247 fn encode_as_type_to<R: TypeResolver>(
248 &self,
249 type_id: R::TypeId,
250 types: &R,
251 out: &mut Vec<u8>,
252 ) -> Result<(), Error> {
253 let type_id = find_single_entry_with_same_repr(type_id, types);
254
255 let wrong_shape_err = |type_id| {
256 Error::new(ErrorKind::WrongShape {
257 actual: Kind::Number,
258 expected_id: format!("{type_id:?}"),
259 })
260 };
261
262 let v = visitor::new((type_id.clone(), out), |(type_id, _out), _kind| Err(wrong_shape_err(type_id)))
263 .visit_primitive(|(type_id, out), primitive| {
264 fn try_num<T: TryFrom<$ty> + Encode>(
265 num: $ty,
266 target_id: impl core::fmt::Debug,
267 out: &mut Vec<u8>,
268 ) -> Result<(), Error> {
269 let n: T = num.try_into().map_err(|_| {
270 Error::new(ErrorKind::NumberOutOfRange {
271 value: num.to_string(),
272 expected_id: format!("{target_id:?}"),
273 })
274 })?;
275 n.encode_to(out);
276 Ok(())
277 }
278
279 match primitive {
280 Primitive::U8 => try_num::<u8>(*self, type_id, out),
281 Primitive::U16 => try_num::<u16>(*self, type_id, out),
282 Primitive::U32 => try_num::<u32>(*self, type_id, out),
283 Primitive::U64 => try_num::<u64>(*self, type_id, out),
284 Primitive::U128 => try_num::<u128>(*self, type_id, out),
285 Primitive::I8 => try_num::<i8>(*self, type_id, out),
286 Primitive::I16 => try_num::<i16>(*self, type_id, out),
287 Primitive::I32 => try_num::<i32>(*self, type_id, out),
288 Primitive::I64 => try_num::<i64>(*self, type_id, out),
289 Primitive::I128 => try_num::<i128>(*self, type_id, out),
290 _ => Err(wrong_shape_err(type_id)),
291 }
292 })
293 .visit_compact(|(_,out), inner_type_id| {
294 let inner_type_id = find_single_entry_with_same_repr(inner_type_id, types);
295
296 macro_rules! try_compact_num {
297 ($num:expr, $inner_type_id:ident, $target_kind:expr, $out:expr, $type:ty) => {{
298 let n: $type = $num.try_into().map_err(|_| {
299 Error::new(ErrorKind::NumberOutOfRange {
300 value: $num.to_string(),
301 expected_id: format!("{:?}", $inner_type_id),
302 })
303 })?;
304 Compact(n).encode_to($out);
305 Ok(())
306 }};
307 }
308
309 let v = visitor::new((inner_type_id.clone(),out), |(inner_type_id,_out), _| Err(wrong_shape_err(inner_type_id))).visit_primitive(
310 |(inner_type_id,out), primitive| match primitive {
311 Primitive::U8 => {
312 try_compact_num!(*self, inner_type_id, NumericKind::U8, out, u8)
313 }
314 Primitive::U16 => {
315 try_compact_num!(*self, inner_type_id, NumericKind::U16, out, u16)
316 }
317 Primitive::U32 => {
318 try_compact_num!(*self, inner_type_id, NumericKind::U32, out, u32)
319 }
320 Primitive::U64 => {
321 try_compact_num!(*self, inner_type_id, NumericKind::U64, out, u64)
322 }
323 Primitive::U128 => {
324 try_compact_num!(*self, inner_type_id, NumericKind::U128, out, u128)
325 }
326 _ => Err(wrong_shape_err(inner_type_id)),
327 },
328 );
329
330 resolve_type_and_encode(types, inner_type_id, v)
331 })
332 .visit_not_found(|(type_id,_out)| {
333 Err(Error::new(ErrorKind::TypeNotFound(format!("{type_id:?}"))))
334 });
335
336 resolve_type_and_encode(types, type_id, v)
337 }
338 }
339 };
340}
341impl_encode_number!(u8);
342impl_encode_number!(u16);
343impl_encode_number!(u32);
344impl_encode_number!(u64);
345impl_encode_number!(u128);
346impl_encode_number!(usize);
347impl_encode_number!(i8);
348impl_encode_number!(i16);
349impl_encode_number!(i32);
350impl_encode_number!(i64);
351impl_encode_number!(i128);
352impl_encode_number!(isize);
353
354macro_rules! impl_encode_tuple {
356 ($($name:ident: $t:ident),*) => {
357 impl < $($t),* > EncodeAsType for ($($t,)*) where $($t: EncodeAsType),* {
358 fn encode_as_type_to<Resolver: TypeResolver>(&self, type_id: Resolver::TypeId, types: &Resolver, out: &mut Vec<u8>) -> Result<(), Error> {
359 let ($($name,)*) = self;
360 Composite::new([
361 $(
362 (None as Option<&'static str>, CompositeField::new($name))
363 ,)*
364 ].iter().copied()).encode_composite_as_type_to(type_id, types, out)
365 }
366 }
367 }
368}
369#[rustfmt::skip]
370const _: () = {
371 impl_encode_tuple!();
372 impl_encode_tuple!(a: A);
373 impl_encode_tuple!(a: A, b: B);
374 impl_encode_tuple!(a: A, b: B, c: C);
375 impl_encode_tuple!(a: A, b: B, c: C, d: D);
376 impl_encode_tuple!(a: A, b: B, c: C, d: D, e: E);
377 impl_encode_tuple!(a: A, b: B, c: C, d: D, e: E, f: F);
378 impl_encode_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
379 impl_encode_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
380 impl_encode_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
381 impl_encode_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
382 impl_encode_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K);
383 impl_encode_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L);
384 impl_encode_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M);
385 impl_encode_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N);
386 impl_encode_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O);
387 impl_encode_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O, p: P);
388 impl_encode_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O, p: P, q: Q);
389 impl_encode_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O, p: P, q: Q, r: R);
390 impl_encode_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O, p: P, q: Q, r: R, s: S);
391 };
393
394macro_rules! impl_encode_seq_via_iterator {
396 ($ty:ident $( [$($param:ident),+] )?) => {
397 impl $(< $($param),+ >)? EncodeAsType for $ty $(< $($param),+ >)?
398 where $( $($param: EncodeAsType),+ )?
399 {
400 fn encode_as_type_to<R: TypeResolver>(
401 &self,
402 type_id: R::TypeId,
403 types: &R,
404 out: &mut Vec<u8>,
405 ) -> Result<(), Error> {
406 encode_iterable_sequence_to(self.len(), self.iter(), type_id, types, out)
407 }
408 }
409 }
410}
411impl_encode_seq_via_iterator!(BTreeSet[K]);
412impl_encode_seq_via_iterator!(LinkedList[V]);
413impl_encode_seq_via_iterator!(BinaryHeap[V]);
414impl_encode_seq_via_iterator!(VecDeque[V]);
415impl_encode_seq_via_iterator!(Vec[V]);
416
417impl<K: AsRef<str>, V: EncodeAsType> EncodeAsType for BTreeMap<K, V> {
418 fn encode_as_type_to<R: TypeResolver>(
419 &self,
420 type_id: R::TypeId,
421 types: &R,
422 out: &mut Vec<u8>,
423 ) -> Result<(), Error> {
424 let v = visitor::new((type_id.clone(), out), |(type_id, out), _| {
425 Composite::new(
426 self.iter()
427 .map(|(k, v)| (Some(k.as_ref()), CompositeField::new(v))),
428 )
429 .encode_composite_as_type_to(type_id, types, out)
430 })
431 .visit_array(|(type_id, out), _, _| {
432 encode_iterable_sequence_to(self.len(), self.values(), type_id, types, out)
433 })
434 .visit_sequence(|(type_id, out), _, _| {
435 encode_iterable_sequence_to(self.len(), self.values(), type_id, types, out)
436 });
437
438 resolve_type_and_encode(types, type_id, v)
439 }
440}
441impl<K: AsRef<str>, V: EncodeAsType> EncodeAsFields for BTreeMap<K, V> {
442 fn encode_as_fields_to<R: TypeResolver>(
443 &self,
444 fields: &mut dyn FieldIter<'_, R::TypeId>,
445 types: &R,
446 out: &mut Vec<u8>,
447 ) -> Result<(), Error> {
448 Composite::new(
449 self.iter()
450 .map(|(k, v)| (Some(k.as_ref()), CompositeField::new(v))),
451 )
452 .encode_composite_fields_to(fields, types, out)
453 }
454}
455
456impl<const N: usize, V: EncodeAsType> EncodeAsFields for [V; N] {
457 fn encode_as_fields_to<R: TypeResolver>(
458 &self,
459 fields: &mut dyn FieldIter<'_, R::TypeId>,
460 types: &R,
461 out: &mut Vec<u8>,
462 ) -> Result<(), Error> {
463 Composite::new(self.iter().map(|v| (None, CompositeField::new(v))))
464 .encode_composite_fields_to(fields, types, out)
465 }
466}
467
468impl<V: EncodeAsType> EncodeAsFields for &[V] {
469 fn encode_as_fields_to<R: TypeResolver>(
470 &self,
471 fields: &mut dyn FieldIter<'_, R::TypeId>,
472 types: &R,
473 out: &mut Vec<u8>,
474 ) -> Result<(), Error> {
475 Composite::new(self.iter().map(|v| (None, CompositeField::new(v))))
476 .encode_composite_fields_to(fields, types, out)
477 }
478}
479
480impl<V: EncodeAsType> EncodeAsFields for Vec<V> {
481 fn encode_as_fields_to<R: TypeResolver>(
482 &self,
483 fields: &mut dyn FieldIter<'_, R::TypeId>,
484 types: &R,
485 out: &mut Vec<u8>,
486 ) -> Result<(), Error> {
487 Composite::new(self.iter().map(|v| (None, CompositeField::new(v))))
488 .encode_composite_fields_to(fields, types, out)
489 }
490}
491
492macro_rules! impl_tuple_encode_as_fields {
493 ($($param:ident $idx:tt),+) => {
494 impl <$($param: EncodeAsType),+> EncodeAsFields for ($($param,)+) {
495 fn encode_as_fields_to<R: TypeResolver>(
496 &self,
497 fields: &mut dyn FieldIter<'_, R::TypeId>,
498 types: &R,
499 out: &mut Vec<u8>,
500 ) -> Result<(), Error> {
501 Composite::new(
502 [
503 $(
504 (None, CompositeField::new(&self.$idx))
505 ),+
506 ].into_iter(),
507 )
508 .encode_composite_fields_to(fields, types, out)
509 }
510 }
511 }
512}
513
514impl_tuple_encode_as_fields!(A 0);
515impl_tuple_encode_as_fields!(A 0, B 1);
516impl_tuple_encode_as_fields!(A 0, B 1, C 2);
517impl_tuple_encode_as_fields!(A 0, B 1, C 2, D 3);
518impl_tuple_encode_as_fields!(A 0, B 1, C 2, D 3, E 4);
519impl_tuple_encode_as_fields!(A 0, B 1, C 2, D 3, E 4, F 5);
520impl_tuple_encode_as_fields!(A 0, B 1, C 2, D 3, E 4, F 5, G 6);
521impl_tuple_encode_as_fields!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7);
522impl_tuple_encode_as_fields!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8);
523impl_tuple_encode_as_fields!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9);
524impl_tuple_encode_as_fields!(A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10);
525
526impl EncodeAsFields for () {
527 fn encode_as_fields_to<R: TypeResolver>(
528 &self,
529 fields: &mut dyn FieldIter<'_, R::TypeId>,
530 _types: &R,
531 _out: &mut Vec<u8>,
532 ) -> Result<(), Error> {
533 if fields.len() != 0 {
534 Err(Error::new(ErrorKind::WrongLength {
535 actual_len: 0,
536 expected_len: fields.len(),
537 }))
538 } else {
539 Ok(())
540 }
541 }
542}
543
544macro_rules! impl_encode_like {
547 ($ty:ident $(<$( $param:ident ),+>)? as $delegate_ty:ty where |$val:ident| $expr:expr) => {
548 impl $(< $($param: EncodeAsType),+ >)? EncodeAsType for $ty $(<$( $param ),+>)? {
549 fn encode_as_type_to<R: TypeResolver>(
550 &self,
551 type_id: R::TypeId,
552 types: &R,
553 out: &mut Vec<u8>,
554 ) -> Result<(), Error> {
555 let delegate: $delegate_ty = {
556 let $val = self;
557 $expr
558 };
559 delegate.encode_as_type_to(type_id, types, out)
560 }
561 }
562 }
563}
564impl_encode_like!(String as &str where |val| val);
565impl_encode_like!(Box<T> as &T where |val| val);
566impl_encode_like!(Arc<T> as &T where |val| val);
567impl_encode_like!(Rc<T> as &T where |val| val);
568impl_encode_like!(char as u32 where |val| *val as u32);
569impl_encode_like!(NonZeroU8 as u8 where |val| val.get());
570impl_encode_like!(NonZeroU16 as u16 where |val| val.get());
571impl_encode_like!(NonZeroU32 as u32 where |val| val.get());
572impl_encode_like!(NonZeroU64 as u64 where |val| val.get());
573impl_encode_like!(NonZeroU128 as u128 where |val| val.get());
574impl_encode_like!(NonZeroI8 as i8 where |val| val.get());
575impl_encode_like!(NonZeroI16 as i16 where |val| val.get());
576impl_encode_like!(NonZeroI32 as i32 where |val| val.get());
577impl_encode_like!(NonZeroI64 as i64 where |val| val.get());
578impl_encode_like!(NonZeroI128 as i128 where |val| val.get());
579impl_encode_like!(Duration as (u64, u32) where |val| (val.as_secs(), val.subsec_nanos()));
580impl_encode_like!(Range<T> as (&T, &T) where |val| (&val.start, &val.end));
581impl_encode_like!(RangeInclusive<T> as (&T, &T) where |val| ((val.start()), (val.end())));
582impl_encode_like!(Compact<T> as &T where |val| &val.0);
583
584macro_rules! impl_encode_like_to_fields {
587 ($ty:ident $(<$( $param:ident ),+>)? as $delegate_ty:ty where |$val:ident| $expr:expr) => {
588 impl $(< $($param: EncodeAsFields),+ >)? EncodeAsFields for $ty $(<$( $param ),+>)? {
589 fn encode_as_fields_to<R: TypeResolver>(
590 &self,
591 fields: &mut dyn FieldIter<'_, R::TypeId>,
592 types: &R,
593 out: &mut Vec<u8>,
594 ) -> Result<(), Error> {
595 self.as_ref().encode_as_fields_to(fields, types, out)
596 }
597 }
598 }
599}
600impl_encode_like_to_fields!(Box<T> as &T where |val| val);
601impl_encode_like_to_fields!(Rc<T> as &T where |val| val);
602impl_encode_like_to_fields!(Arc<T> as &T where |val| val);
603
604fn find_single_entry_with_same_repr<R: TypeResolver>(type_id: R::TypeId, types: &R) -> R::TypeId {
608 let v = visitor::new(type_id.clone(), |type_id, _| type_id)
609 .visit_tuple(|type_id, fields| {
610 let Some(new_type_id) = fields.next() else {
611 return type_id;
612 };
613 if fields.next().is_some() {
614 return type_id;
615 }
616 find_single_entry_with_same_repr(new_type_id, types)
617 })
618 .visit_composite(|type_id, _, fields| {
619 let Some(field) = fields.next() else {
620 return type_id;
621 };
622 if fields.next().is_some() {
623 return type_id;
624 }
625 find_single_entry_with_same_repr(field.id, types)
626 });
627
628 types.resolve_type(type_id.clone(), v).unwrap_or(type_id)
629}
630
631fn encode_iterable_sequence_to<I, R>(
633 len: usize,
634 it: I,
635 type_id: R::TypeId,
636 types: &R,
637 out: &mut Vec<u8>,
638) -> Result<(), Error>
639where
640 I: Iterator,
641 I::Item: EncodeAsType,
642 R: TypeResolver,
643{
644 let wrong_shape_err = |type_id| {
645 Error::new(ErrorKind::WrongShape {
646 actual: Kind::Array,
647 expected_id: format!("{type_id:?}"),
648 })
649 };
650
651 let v = visitor::new((type_id.clone(), it, out), |(type_id, _, _), _| {
652 Err(wrong_shape_err(type_id))
653 })
654 .visit_array(|(_, it, out), inner_ty_id: R::TypeId, array_len| {
655 if array_len == len {
656 for (idx, item) in it.enumerate() {
657 item.encode_as_type_to(inner_ty_id.clone(), types, out)
658 .map_err(|e| e.at_idx(idx))?;
659 }
660 Ok(())
661 } else {
662 Err(Error::new(ErrorKind::WrongLength {
663 actual_len: len,
664 expected_len: array_len,
665 }))
666 }
667 })
668 .visit_sequence(|(_, it, out), _, inner_ty_id| {
669 Compact(len as u32).encode_to(out);
671 for (idx, item) in it.enumerate() {
672 item.encode_as_type_to(inner_ty_id.clone(), types, out)
673 .map_err(|e| e.at_idx(idx))?;
674 }
675 Ok(())
676 })
677 .visit_tuple(|(type_id, it, out), inner_type_ids| {
678 if inner_type_ids.len() == 1 {
679 encode_iterable_sequence_to(len, it, inner_type_ids.next().unwrap(), types, out)
680 } else {
681 Err(wrong_shape_err(type_id))
682 }
683 })
684 .visit_composite(|(type_id, it, out), _, fields| {
685 if fields.len() == 1 {
686 encode_iterable_sequence_to(len, it, fields.next().unwrap().id, types, out)
687 } else {
688 Err(wrong_shape_err(type_id))
689 }
690 });
691
692 resolve_type_and_encode(types, type_id, v)
693}
694
695#[cfg(all(feature = "derive", feature = "bits", feature = "primitive-types"))]
696#[cfg(test)]
697mod test {
698 use super::*;
699 use crate::{EncodeAsFields, Field};
700 use alloc::vec;
701 use codec::Decode;
702 use core::fmt::Debug;
703 use scale_info::{PortableRegistry, TypeInfo};
704
705 fn make_type<T: TypeInfo + 'static>() -> (u32, PortableRegistry) {
707 let m = scale_info::MetaType::new::<T>();
708 let mut types = scale_info::Registry::new();
709 let id = types.register_type(&m);
710 let portable_registry: PortableRegistry = types.into();
711
712 (id.id, portable_registry)
713 }
714
715 fn encode_type<V: EncodeAsType, T: TypeInfo + 'static>(value: V) -> Result<Vec<u8>, Error> {
716 let (type_id, types) = make_type::<T>();
717 let bytes = value.encode_as_type(type_id, &types)?;
718 Ok(bytes)
719 }
720
721 fn assert_value_roundtrips_to<
722 V: EncodeAsType,
723 T: PartialEq + Debug + Decode + TypeInfo + 'static,
724 >(
725 value: V,
726 target: T,
727 ) {
728 let bytes = encode_type::<_, T>(&value).expect("can encode");
729 let bytes_cursor = &mut &*bytes;
730 let new_target = T::decode(bytes_cursor).expect("can decode");
731
732 assert_eq!(bytes_cursor.len(), 0, "no bytes should be remaining");
733 assert_eq!(
734 target, new_target,
735 "value does not roundtrip and decode to target"
736 );
737 }
738
739 fn assert_encodes_like_codec<
740 V: Encode + EncodeAsType + PartialEq + Debug + TypeInfo + 'static,
741 >(
742 value: V,
743 ) {
744 let encode_bytes = value.encode();
745 let bytes = encode_type::<V, V>(value).expect("can encode");
746 assert_eq!(
747 bytes, encode_bytes,
748 "scale-encode encoded differently from parity-scale-codec"
749 );
750 }
751
752 fn assert_encodes_fields_like_type<V: EncodeAsFields, T: TypeInfo + Encode + 'static>(
753 value: V,
754 other: T,
755 ) {
756 let encoded_other = other.encode();
757
758 let (type_id, types) = make_type::<T>();
759 let type_def = &types.resolve(type_id).unwrap().type_def;
760
761 let encoded_as_fields = match type_def {
762 scale_info::TypeDef::Composite(c) => {
763 let mut fields = c
764 .fields
765 .iter()
766 .map(|f| Field::new(f.ty.id, f.name.as_deref()));
767 value.encode_as_fields(&mut fields, &types).unwrap()
768 }
769 scale_info::TypeDef::Tuple(t) => {
770 let mut fields = t.fields.iter().map(|f| Field::unnamed(f.id));
771 value.encode_as_fields(&mut fields, &types).unwrap()
772 }
773 _ => {
774 panic!("Expected composite or tuple type def");
775 }
776 };
777
778 assert_eq!(
779 encoded_other, encoded_as_fields,
780 "compare encode_with_fields with other encode"
781 );
782 }
783
784 #[test]
785 fn numeric_roundtrips_encode_ok() {
786 macro_rules! int_value_roundtrip {
787 ($($val:expr; $ty:ty),+) => {$(
788 assert_value_roundtrips_to($val, $val as i8);
789 assert_value_roundtrips_to($val, $val as i16);
790 assert_value_roundtrips_to($val, $val as i32);
791 assert_value_roundtrips_to($val, $val as i64);
792 assert_value_roundtrips_to($val, $val as i128);
793 )+}
794 }
795 macro_rules! uint_value_roundtrip {
796 ($($val:expr; $ty:ty),+) => {$(
797 assert_value_roundtrips_to($val, $val as u8);
798 assert_value_roundtrips_to($val, $val as u16);
799 assert_value_roundtrips_to($val, $val as u32);
800 assert_value_roundtrips_to($val, $val as u64);
801 assert_value_roundtrips_to($val, $val as u128);
802 )+}
803 }
804 macro_rules! int_value_roundtrip_types {
805 ($($val:expr),+) => {$(
806 int_value_roundtrip!($val; i8);
807 int_value_roundtrip!($val; i16);
808 int_value_roundtrip!($val; i32);
809 int_value_roundtrip!($val; i64);
810 int_value_roundtrip!($val; i128);
811 )+}
812 }
813 macro_rules! uint_value_roundtrip_types {
814 ($($val:expr),+) => {$(
815 uint_value_roundtrip!($val; u8);
816 uint_value_roundtrip!($val; u16);
817 uint_value_roundtrip!($val; u32);
818 uint_value_roundtrip!($val; u64);
819 uint_value_roundtrip!($val; u128);
820 )+}
821 }
822 macro_rules! all_value_roundtrip_types {
823 ($($val:expr),+) => {$(
824 int_value_roundtrip_types!($val);
825 uint_value_roundtrip_types!($val);
826 )+}
827 }
828 uint_value_roundtrip_types!(200);
829 int_value_roundtrip_types!(-127, -100, 0, 1, 100, 127);
830 all_value_roundtrip_types!(0, 1, 100, 127);
831 }
832
833 #[test]
834 fn out_of_range_numeric_roundtrips_fail_to_encode() {
835 encode_type::<_, u8>(&1234u16).unwrap_err();
836 encode_type::<_, i8>(&129u8).unwrap_err();
837 encode_type::<_, u8>(&-10i8).unwrap_err();
838 }
839
840 #[test]
841 fn sequence_encodes_like_scale_codec() {
842 let (type_id, types) = make_type::<Vec<u8>>();
843 let e = vec![1u8, 2, 3].encode();
844 let e2 = vec![1u8, 2, 3]
845 .encode_as_type(type_id, &types)
846 .expect("can encode 2");
847 assert_eq!(e, e2);
848 }
849
850 #[test]
851 fn basic_types_encode_like_scale_codec() {
852 assert_encodes_like_codec(true);
853 assert_encodes_like_codec(false);
854 assert_encodes_like_codec("hi");
855 assert_encodes_like_codec("hi".to_string());
856 assert_encodes_like_codec(Box::new("hi"));
857 assert_encodes_like_codec(-1234);
858 assert_encodes_like_codec(100_000_000_000_000u128);
859 assert_encodes_like_codec(());
860 assert_encodes_like_codec(core::marker::PhantomData::<()>);
861 assert_encodes_like_codec([1, 2, 3, 4, 5]);
862 assert_encodes_like_codec([1u8, 2, 3, 4, 5]);
863 assert_encodes_like_codec(vec![1, 2, 3, 4, 5]);
864 assert_encodes_like_codec([1, 2, 3, 4, 5]);
865 assert_encodes_like_codec(Some(1234u32));
866 assert_encodes_like_codec(None as Option<bool>);
867 assert_encodes_like_codec(Ok::<_, &str>("hello"));
868 assert_encodes_like_codec(Err::<u32, _>("aah"));
869 assert_encodes_like_codec(0..100);
870 assert_encodes_like_codec(0..=100);
871
872 assert_value_roundtrips_to(Arc::new("hi"), "hi".to_string());
874 assert_value_roundtrips_to(Rc::new("hi"), "hi".to_string());
875 }
877
878 #[test]
879 fn other_container_types_roundtrip_ok() {
880 let v = LinkedList::from([1u8, 2, 3]);
884 assert_value_roundtrips_to(v, vec![1u8, 2, 3]);
885
886 let v = BinaryHeap::from([2, 3, 1]);
888 assert_value_roundtrips_to(v, vec![3u8, 2, 1]);
889
890 let v = BTreeSet::from([1u8, 2, 3]);
891 assert_value_roundtrips_to(v, vec![1u8, 2, 3]);
892
893 let v = VecDeque::from([1u8, 2, 3]);
894 assert_value_roundtrips_to(v, vec![1u8, 2, 3]);
895 }
896
897 #[test]
898 fn btreemap_can_encode_to_struct() {
899 #[derive(Debug, scale_info::TypeInfo, codec::Decode, PartialEq)]
900 struct Foo {
901 a: u8,
902 b: u16,
903 c: u32,
904 }
905
906 let v = BTreeMap::from([("a", 1), ("c", 2), ("b", 3)]);
907
908 assert_value_roundtrips_to(v.clone(), Foo { a: 1, b: 3, c: 2 });
910 assert_value_roundtrips_to(v, (1, 3, 2));
912 }
913
914 #[test]
915 fn mixed_tuples_roundtrip_ok() {
916 assert_encodes_like_codec(());
917 assert_encodes_like_codec((12345,));
918 assert_encodes_like_codec((123u8, true));
919 assert_encodes_like_codec((123u8, true, "hello"));
920 assert_encodes_like_codec((123u8, true, "hello".to_string(), 'a' as u32));
922 assert_encodes_like_codec((
923 123u8,
924 true,
925 "hello".to_string(),
926 'a' as u32,
927 123_000_000_000u128,
928 ));
929 }
930
931 #[test]
932 fn sequences_roundtrip_into_eachother() {
933 assert_value_roundtrips_to(([1u8, 2u8, 3u8],), vec![1u8, 2u8, 3u8]);
935 assert_value_roundtrips_to(([(1u8,), (2u8,), (3u8,)],), (([1u8, 2u8, 3u8],),));
936 assert_value_roundtrips_to(((([1u8],),),), (([1u8],),));
937 assert_value_roundtrips_to((([(1u8,)],),), (([1u8],),));
938 }
939
940 #[test]
941 fn tuples_to_structs() {
942 #[derive(Debug, scale_info::TypeInfo, codec::Decode, PartialEq)]
943 struct Foo {
944 a: (u32,),
945 b: u64,
946 c: u128,
947 }
948 assert_value_roundtrips_to(
949 (1u8, 2u8, 3u8),
950 Foo {
951 a: (1,),
952 b: 2,
953 c: 3,
954 },
955 );
956 }
957
958 #[test]
959 fn values_roundtrip_into_wrappers() {
960 #[derive(Debug, scale_info::TypeInfo, codec::Decode, PartialEq)]
961 struct Wrapper<T> {
962 val: T,
963 }
964
965 assert_value_roundtrips_to(true, (true,));
966 assert_value_roundtrips_to(1234u16, (1234u16,));
967 assert_value_roundtrips_to(1234u16, Wrapper { val: 1234u16 });
968 assert_value_roundtrips_to("hi", (("hi".to_string(),),));
969 assert_value_roundtrips_to(
970 "hi",
971 (Wrapper {
972 val: "hi".to_string(),
973 },),
974 );
975 }
976
977 #[test]
978 fn compacts_roundtrip() {
979 assert_encodes_like_codec(Compact(123u16));
980 assert_encodes_like_codec(Compact(123u8));
981 assert_encodes_like_codec(Compact(123u64));
982 }
983
984 #[test]
985 fn tuple_composite_can_encode_to_named_structs() {
986 #[derive(Debug, scale_info::TypeInfo, codec::Decode, PartialEq)]
987 struct Foo {
988 bar: u32,
989 wibble: bool,
990 hello: String,
991 }
992
993 let source_vals = [
995 (Some("hello"), CompositeField::new(&"world")),
996 (Some("bar"), CompositeField::new(&12345u128)),
997 (Some("wibble"), CompositeField::new(&true)),
998 ];
999 let source = Composite::new(source_vals.iter().copied());
1000
1001 let (type_id, types) = make_type::<Foo>();
1003 let bytes = source.encode_composite_as_type(type_id, &types).unwrap();
1004 let cursor = &mut &*bytes;
1005
1006 let target = Foo {
1007 bar: 12345,
1008 wibble: true,
1009 hello: "world".to_string(),
1010 };
1011
1012 let new_target = Foo::decode(cursor).unwrap();
1013
1014 assert_eq!(target, new_target);
1015 assert_eq!(cursor.len(), 0);
1016 }
1017
1018 #[test]
1019 fn tuple_composite_can_encode_to_unnamed_structs() {
1020 #[derive(Debug, scale_info::TypeInfo, codec::Decode, PartialEq, Clone)]
1021 struct Foo(u32, bool, String);
1022 let (type_id, types) = make_type::<Foo>();
1023
1024 let source_vals = [
1026 (Some("bar"), CompositeField::new(&12345u128)),
1027 (Some("wibble"), CompositeField::new(&true)),
1028 (Some("hello"), CompositeField::new(&"world")),
1029 ];
1030 let source = Composite::new(source_vals.iter().copied());
1031 let source_bytes = source.encode_composite_as_type(type_id, &types).unwrap();
1032 let source_cursor = &mut &*source_bytes;
1033
1034 let source2_vals = [
1035 (None, CompositeField::new(&12345u128)),
1036 (None, CompositeField::new(&true)),
1037 (None, CompositeField::new(&"world")),
1038 ];
1039 let source2 = Composite::new(source2_vals.iter().copied());
1040 let source2_bytes = source2.encode_composite_as_type(type_id, &types).unwrap();
1041 let source2_cursor = &mut &*source2_bytes;
1042
1043 let target = Foo(12345, true, "world".to_string());
1044 let new_target = Foo::decode(source_cursor).unwrap();
1045 let new_target2 = Foo::decode(source2_cursor).unwrap();
1046
1047 assert_eq!(target, new_target);
1048 assert_eq!(target, new_target2);
1049 assert_eq!(source_cursor.len(), 0);
1050 assert_eq!(source2_cursor.len(), 0);
1051 }
1052
1053 #[test]
1054 fn tuple_composite_names_must_line_up() {
1055 #[derive(Debug, scale_info::TypeInfo, codec::Decode, PartialEq)]
1056 struct Foo {
1057 bar: u32,
1058 wibble: bool,
1059 hello: String,
1060 }
1061
1062 let source_vals = [
1064 (Some("hello"), CompositeField::new(&"world")),
1065 (Some("bar"), CompositeField::new(&12345u128)),
1066 (Some("wibbles"), CompositeField::new(&true)),
1068 ];
1069 let source = Composite::new(source_vals.iter().copied());
1070
1071 let (type_id, types) = make_type::<Foo>();
1072 let _bytes = source
1073 .encode_composite_as_type(type_id, &types)
1074 .unwrap_err();
1075 }
1076
1077 #[test]
1078 fn bits_roundtrip_ok() {
1079 use bitvec::{
1080 order::{Lsb0, Msb0},
1081 vec::BitVec,
1082 };
1083 use scale_bits::Bits;
1084
1085 fn test_bits(bits: impl IntoIterator<Item = bool> + Clone) {
1086 let source = Bits::from_iter(bits.clone());
1087
1088 let target = BitVec::<u8, Lsb0>::from_iter(bits.clone());
1089 assert_value_roundtrips_to(source.clone(), target);
1090 let target = BitVec::<u16, Lsb0>::from_iter(bits.clone());
1091 assert_value_roundtrips_to(source.clone(), target);
1092 let target = BitVec::<u32, Lsb0>::from_iter(bits.clone());
1093 assert_value_roundtrips_to(source.clone(), target);
1094 let target = BitVec::<u64, Lsb0>::from_iter(bits.clone());
1095 assert_value_roundtrips_to(source.clone(), target);
1096 let target = BitVec::<u8, Msb0>::from_iter(bits.clone());
1097 assert_value_roundtrips_to(source.clone(), target);
1098 let target = BitVec::<u16, Msb0>::from_iter(bits.clone());
1099 assert_value_roundtrips_to(source.clone(), target);
1100 let target = BitVec::<u32, Msb0>::from_iter(bits.clone());
1101 assert_value_roundtrips_to(source.clone(), target);
1102 let target = BitVec::<u64, Msb0>::from_iter(bits);
1103 assert_value_roundtrips_to(source, target);
1104 }
1105
1106 test_bits([]);
1107 test_bits([true]);
1108 test_bits([false]);
1109 test_bits([true, false, true, true, false]);
1110 test_bits([
1111 true, false, true, true, false, true, false, true, true, false, false,
1112 ]);
1113
1114 assert_value_roundtrips_to(
1116 Bits::from_iter([true, false, true]),
1117 ((BitVec::<u8, Lsb0>::from_iter([true, false, true]),),),
1118 );
1119 assert_value_roundtrips_to(
1120 (Bits::from_iter([true, false, true]),),
1121 ((BitVec::<u8, Lsb0>::from_iter([true, false, true]),),),
1122 );
1123 }
1124
1125 #[test]
1126 fn hxxx_types_roundtrip_ok() {
1127 use ::primitive_types::{H128, H160, H256, H384, H512, H768};
1128
1129 fn test_hxxx(bytes: impl IntoIterator<Item = u8> + Clone) {
1131 let mut bytes: Vec<u8> = bytes.into_iter().collect();
1132
1133 while bytes.len() < 128 / 8 {
1134 bytes.push(0)
1135 }
1136 assert_value_roundtrips_to(H128::from_slice(&bytes), bytes.clone());
1137 assert_value_roundtrips_to(H128::from_slice(&bytes), H128::from_slice(&bytes));
1138
1139 while bytes.len() < 160 / 8 {
1140 bytes.push(0)
1141 }
1142 assert_value_roundtrips_to(H160::from_slice(&bytes), bytes.clone());
1143 assert_value_roundtrips_to(H160::from_slice(&bytes), H160::from_slice(&bytes));
1144
1145 while bytes.len() < 256 / 8 {
1146 bytes.push(0)
1147 }
1148 assert_value_roundtrips_to(H256::from_slice(&bytes), bytes.clone());
1149 assert_value_roundtrips_to(H256::from_slice(&bytes), H256::from_slice(&bytes));
1150
1151 while bytes.len() < 384 / 8 {
1152 bytes.push(0)
1153 }
1154 assert_value_roundtrips_to(H384::from_slice(&bytes), bytes.clone());
1155 assert_value_roundtrips_to(H384::from_slice(&bytes), H384::from_slice(&bytes));
1156
1157 while bytes.len() < 512 / 8 {
1158 bytes.push(0)
1159 }
1160 assert_value_roundtrips_to(H512::from_slice(&bytes), bytes.clone());
1161 assert_value_roundtrips_to(H512::from_slice(&bytes), H512::from_slice(&bytes));
1162
1163 while bytes.len() < 768 / 8 {
1164 bytes.push(0)
1165 }
1166 assert_value_roundtrips_to(H768::from_slice(&bytes), bytes.clone());
1167 assert_value_roundtrips_to(H768::from_slice(&bytes), H768::from_slice(&bytes));
1168 }
1169
1170 test_hxxx([0u8]);
1171 test_hxxx([1, 2, 3, 4]);
1172 }
1173
1174 #[test]
1175 fn encode_as_fields_works() {
1176 #[derive(TypeInfo, Encode)]
1177 struct Foo {
1178 some_field: u64,
1179 another: u8,
1180 }
1181
1182 assert_encodes_fields_like_type(
1183 BTreeMap::from([
1184 ("other1", 1),
1185 ("another", 2),
1186 ("some_field", 3),
1187 ("other2", 4),
1188 ]),
1189 Foo {
1190 some_field: 3,
1191 another: 2,
1192 },
1193 );
1194
1195 assert_encodes_fields_like_type(
1196 (1u64, 2u8),
1197 Foo {
1198 some_field: 1,
1199 another: 2,
1200 },
1201 );
1202
1203 assert_encodes_fields_like_type(
1204 vec![1u64, 2u64],
1205 Foo {
1206 some_field: 1,
1207 another: 2,
1208 },
1209 );
1210
1211 assert_encodes_fields_like_type(
1212 [1u64, 2u64],
1213 Foo {
1214 some_field: 1,
1215 another: 2,
1216 },
1217 );
1218
1219 assert_encodes_fields_like_type(
1220 &[1u64, 2u64][..],
1221 Foo {
1222 some_field: 1,
1223 another: 2,
1224 },
1225 );
1226 }
1227
1228 #[test]
1229 fn encode_as_fields_via_macro_works() {
1230 #[derive(TypeInfo, Encode)]
1231 struct Foo {
1232 some_field: u64,
1233 another: bool,
1234 }
1235
1236 #[derive(TypeInfo, Encode)]
1237 struct FooUnnamed(
1238 String,
1239 (u8,), bool,
1241 u8,
1242 );
1243
1244 #[derive(EncodeAsType)]
1245 #[encode_as_type(crate_path = "crate")]
1246 struct FooBigger {
1247 random: String,
1248 some_field: u64,
1249 another: bool,
1250 more_random: u8,
1251 }
1252
1253 assert_encodes_fields_like_type(
1254 FooBigger {
1255 random: "hello".to_string(),
1256 some_field: 123,
1257 another: true,
1258 more_random: 1,
1259 },
1260 Foo {
1261 some_field: 123,
1262 another: true,
1263 },
1264 );
1265 assert_encodes_fields_like_type(
1266 FooBigger {
1267 random: "hello".to_string(),
1268 some_field: 123,
1269 another: true,
1270 more_random: 1,
1271 },
1272 FooUnnamed("hello".to_string(), (123,), true, 1),
1273 );
1274 assert_encodes_fields_like_type(
1275 FooBigger {
1276 random: "hello".to_string(),
1277 some_field: 123,
1278 another: true,
1279 more_random: 1,
1280 },
1281 ("hello".to_string(), (123u8,), true, (1u64,)),
1282 );
1283 }
1284
1285 #[test]
1286 #[allow(unused_assignments)]
1287 fn encode_to_number_skipping_attrs_via_macro_works() {
1288 struct NotEncodeAsType;
1289
1290 #[allow(dead_code)]
1291 #[derive(EncodeAsType)]
1292 #[encode_as_type(crate_path = "crate")]
1293 struct FooNotSkipping {
1294 value: u64,
1295 other: bool,
1296 third: String,
1297 }
1298
1299 #[derive(EncodeAsType)]
1300 #[encode_as_type(crate_path = "crate")]
1301 struct FooSkipping {
1302 value: u64,
1303 #[encode_as_type(skip)]
1304 other: bool,
1305 #[codec(skip)]
1308 third: NotEncodeAsType,
1309 }
1310
1311 assert_value_roundtrips_to(
1312 FooSkipping {
1313 value: 123,
1314 other: true,
1315 third: NotEncodeAsType,
1316 },
1317 123u64,
1318 );
1319 }
1320
1321 #[test]
1322 fn encode_unnamed_to_number_skipping_attrs_via_macro_works() {
1323 struct NotEncodeAsType;
1324
1325 #[derive(EncodeAsType)]
1326 #[encode_as_type(crate_path = "crate")]
1327 struct FooSkipping(
1328 u64,
1329 #[encode_as_type(skip)] bool,
1330 #[codec(skip)] NotEncodeAsType,
1333 );
1334
1335 assert_value_roundtrips_to(FooSkipping(123, true, NotEncodeAsType), 123u64);
1336 }
1337
1338 #[test]
1341 #[should_panic]
1342 fn encode_to_number_not_skipping_via_macro_fails() {
1343 #[derive(EncodeAsType)]
1344 #[encode_as_type(crate_path = "crate")]
1345 struct FooNotSkipping {
1346 value: u64,
1347 other: bool,
1348 third: String,
1349 }
1350
1351 assert_value_roundtrips_to(
1352 FooNotSkipping {
1353 value: 123,
1354 other: true,
1355 third: "hello".to_string(),
1356 },
1357 123u64,
1358 );
1359 }
1360
1361 #[test]
1362 fn encode_smart_pointers_as_fields() {
1363 #[derive(TypeInfo, Encode, PartialEq, Debug, Decode)]
1364 struct Foo {
1365 some_field: u64,
1366 another: u8,
1367 }
1368
1369 let map = BTreeMap::from([
1370 ("other1", 1),
1371 ("another", 2),
1372 ("some_field", 3),
1373 ("other2", 4),
1374 ]);
1375 let a = Box::new(map.clone());
1376 assert_encodes_fields_like_type(
1377 a.clone(),
1378 Foo {
1379 some_field: 3,
1380 another: 2,
1381 },
1382 );
1383 assert_value_roundtrips_to(
1384 &a,
1385 Box::new(Foo {
1386 some_field: 3,
1387 another: 2,
1388 }),
1389 );
1390 let b = Rc::new(map.clone());
1391 assert_encodes_fields_like_type(
1392 b.clone(),
1393 Foo {
1394 some_field: 3,
1395 another: 2,
1396 },
1397 );
1398 assert_value_roundtrips_to(
1399 &b,
1400 Rc::new(Foo {
1401 some_field: 3,
1402 another: 2,
1403 }),
1404 );
1405 let c = Arc::new(map.clone());
1406 assert_encodes_fields_like_type(
1407 c.clone(),
1408 Foo {
1409 some_field: 3,
1410 another: 2,
1411 },
1412 );
1413 assert_value_roundtrips_to(
1414 &c,
1415 Arc::new(Foo {
1416 some_field: 3,
1417 another: 2,
1418 }),
1419 );
1420 }
1421}