1use core::marker::PhantomData;
17
18use crate::prelude::*;
19use crate::value_type::{Composite, Primitive, Value, ValueDef, Variant};
20use scale_decode::{FieldIter, TypeResolver};
21
22pub use scale_decode::visitor::DecodeError;
24
25pub type ValueVisitor<Resolver> = DecodeValueVisitor<Resolver, TypeIdContext>;
27
28pub fn decode_value_as_type<R>(
32 data: &mut &[u8],
33 ty_id: R::TypeId,
34 types: &R,
35) -> Result<Value<R::TypeId>, DecodeError>
36where
37 R: TypeResolver,
38 R::TypeId: Clone,
39{
40 scale_decode::visitor::decode_with_visitor(
41 data,
42 ty_id,
43 types,
44 DecodeValueVisitor::<R, TypeIdContext>::new(),
45 )
46}
47
48pub fn decode_composite_as_fields<'resolver, R>(
51 input: &mut &[u8],
52 fields: &mut dyn FieldIter<'resolver, R::TypeId>,
53 types: &'resolver R,
54) -> Result<Composite<R::TypeId>, DecodeError>
55where
56 R: TypeResolver,
57 R::TypeId: Clone,
58{
59 let mut composite = scale_decode::visitor::types::Composite::new(
61 core::iter::empty(),
62 input,
63 fields,
64 types,
65 false,
66 );
67 let val = visit_composite::<R, TypeIdContext>(&mut composite)?;
69 composite.skip_decoding()?;
71 *input = composite.bytes_from_undecoded();
72 Ok(val)
73}
74
75macro_rules! to_unnamed_composite {
77 ($value:ident, $type_id:ident) => {{
78 let mut vals = Vec::with_capacity($value.remaining());
79 while let Some(val) = $value.decode_item(DecodeValueVisitor::<R, F>::new()) {
80 let val = val?;
81 vals.push(val);
82 }
83 Ok(Value {
84 value: ValueDef::Composite(Composite::Unnamed(vals)),
85 context: F::context_from_type_id(&$type_id),
86 })
87 }};
88}
89
90impl scale_decode::DecodeAsFields for Composite<()> {
92 fn decode_as_fields<'resolver, R: TypeResolver>(
93 input: &mut &[u8],
94 fields: &mut dyn FieldIter<'resolver, R::TypeId>,
95 types: &'resolver R,
96 ) -> Result<Self, scale_decode::Error> {
97 let mut composite = scale_decode::visitor::types::Composite::new(
99 core::iter::empty(),
100 input,
101 fields,
102 types,
103 false,
104 );
105 let val = visit_composite::<R, EmptyContext>(&mut composite);
107 composite.skip_decoding()?;
109 *input = composite.bytes_from_undecoded();
110 val.map_err(From::from).map(|v| v.map_context(|_| {}))
111 }
112}
113
114impl scale_decode::IntoVisitor for Value<()> {
115 type AnyVisitor<R: scale_decode::TypeResolver> =
117 scale_decode::visitor::VisitorWithCrateError<DecodeValueVisitor<R, EmptyContext>>;
118
119 fn into_visitor<R: scale_decode::TypeResolver>() -> Self::AnyVisitor<R> {
120 scale_decode::visitor::VisitorWithCrateError(DecodeValueVisitor::new())
121 }
122}
123
124pub trait ContextFromTypeId<TypeId> {
135 type Output;
136 fn context_from_type_id(type_id: &TypeId) -> Self::Output;
137}
138
139pub struct EmptyContext;
141impl<TypeId> ContextFromTypeId<TypeId> for EmptyContext {
142 type Output = ();
143 fn context_from_type_id(_type_id: &TypeId) {}
144}
145
146pub struct TypeIdContext;
148impl<TypeId: Clone> ContextFromTypeId<TypeId> for TypeIdContext {
149 type Output = TypeId;
150 fn context_from_type_id(type_id: &TypeId) -> TypeId {
151 type_id.clone()
152 }
153}
154
155pub struct DecodeValueVisitor<R: TypeResolver, F> {
157 resolver: PhantomData<(R, F)>,
158}
159impl<R: TypeResolver, F> Default for DecodeValueVisitor<R, F> {
160 fn default() -> Self {
161 Self::new()
162 }
163}
164
165impl<R: TypeResolver, F> DecodeValueVisitor<R, F> {
166 pub fn new() -> Self {
167 DecodeValueVisitor { resolver: PhantomData }
168 }
169}
170
171impl<R, F> scale_decode::visitor::Visitor for DecodeValueVisitor<R, F>
172where
173 R: TypeResolver,
174 F: ContextFromTypeId<R::TypeId>,
175{
176 type Value<'scale, 'info> = Value<F::Output>;
177 type Error = DecodeError;
178 type TypeResolver = R;
179
180 fn visit_bool<'scale, 'info>(
181 self,
182 value: bool,
183 type_id: R::TypeId,
184 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
185 Ok(Value::bool(value).map_context(|_| F::context_from_type_id(&type_id)))
186 }
187 fn visit_char<'scale, 'info>(
188 self,
189 value: char,
190 type_id: R::TypeId,
191 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
192 Ok(Value::char(value).map_context(|_| F::context_from_type_id(&type_id)))
193 }
194 fn visit_u8<'scale, 'info>(
195 self,
196 value: u8,
197 type_id: R::TypeId,
198 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
199 self.visit_u128(value as u128, type_id)
200 }
201 fn visit_u16<'scale, 'info>(
202 self,
203 value: u16,
204 type_id: R::TypeId,
205 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
206 self.visit_u128(value as u128, type_id)
207 }
208 fn visit_u32<'scale, 'info>(
209 self,
210 value: u32,
211 type_id: R::TypeId,
212 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
213 self.visit_u128(value as u128, type_id)
214 }
215 fn visit_u64<'scale, 'info>(
216 self,
217 value: u64,
218 type_id: R::TypeId,
219 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
220 self.visit_u128(value as u128, type_id)
221 }
222 fn visit_u128<'scale, 'info>(
223 self,
224 value: u128,
225 type_id: R::TypeId,
226 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
227 Ok(Value::u128(value).map_context(|_| F::context_from_type_id(&type_id)))
228 }
229 fn visit_u256<'info>(
230 self,
231 value: &[u8; 32],
232 type_id: R::TypeId,
233 ) -> Result<Self::Value<'_, 'info>, Self::Error> {
234 Ok(Value {
235 value: ValueDef::Primitive(Primitive::U256(*value)),
236 context: F::context_from_type_id(&type_id),
237 })
238 }
239 fn visit_i8<'scale, 'info>(
240 self,
241 value: i8,
242 type_id: R::TypeId,
243 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
244 self.visit_i128(value as i128, type_id)
245 }
246 fn visit_i16<'scale, 'info>(
247 self,
248 value: i16,
249 type_id: R::TypeId,
250 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
251 self.visit_i128(value as i128, type_id)
252 }
253 fn visit_i32<'scale, 'info>(
254 self,
255 value: i32,
256 type_id: R::TypeId,
257 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
258 self.visit_i128(value as i128, type_id)
259 }
260 fn visit_i64<'scale, 'info>(
261 self,
262 value: i64,
263 type_id: R::TypeId,
264 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
265 self.visit_i128(value as i128, type_id)
266 }
267 fn visit_i128<'scale, 'info>(
268 self,
269 value: i128,
270 type_id: R::TypeId,
271 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
272 Ok(Value::i128(value).map_context(|_| F::context_from_type_id(&type_id)))
273 }
274 fn visit_i256<'info>(
275 self,
276 value: &[u8; 32],
277 type_id: R::TypeId,
278 ) -> Result<Self::Value<'_, 'info>, Self::Error> {
279 Ok(Value {
280 value: ValueDef::Primitive(Primitive::U256(*value)),
281 context: F::context_from_type_id(&type_id),
282 })
283 }
284 fn visit_sequence<'scale, 'info>(
285 self,
286 value: &mut scale_decode::visitor::types::Sequence<'scale, 'info, R>,
287 type_id: R::TypeId,
288 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
289 to_unnamed_composite!(value, type_id)
290 }
291 fn visit_tuple<'scale, 'info>(
292 self,
293 value: &mut scale_decode::visitor::types::Tuple<'scale, 'info, R>,
294 type_id: R::TypeId,
295 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
296 to_unnamed_composite!(value, type_id)
297 }
298 fn visit_array<'scale, 'info>(
299 self,
300 value: &mut scale_decode::visitor::types::Array<'scale, 'info, R>,
301 type_id: R::TypeId,
302 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
303 to_unnamed_composite!(value, type_id)
304 }
305 fn visit_bitsequence<'scale, 'info>(
306 self,
307 value: &mut scale_decode::visitor::types::BitSequence<'scale>,
308 type_id: R::TypeId,
309 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
310 let bits: Result<_, _> = value.decode()?.collect();
311 Ok(Value {
312 value: ValueDef::BitSequence(bits?),
313 context: F::context_from_type_id(&type_id),
314 })
315 }
316 fn visit_str<'scale, 'info>(
317 self,
318 value: &mut scale_decode::visitor::types::Str<'scale>,
319 type_id: R::TypeId,
320 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
321 Ok(Value::string(value.as_str()?).map_context(|_| F::context_from_type_id(&type_id)))
322 }
323 fn visit_variant<'scale, 'info>(
324 self,
325 value: &mut scale_decode::visitor::types::Variant<'scale, 'info, R>,
326 type_id: R::TypeId,
327 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
328 let values = visit_composite::<R, F>(value.fields())?;
329 Ok(Value {
330 value: ValueDef::Variant(Variant { name: value.name().to_owned(), values }),
331 context: F::context_from_type_id(&type_id),
332 })
333 }
334 fn visit_composite<'scale, 'info>(
335 self,
336 value: &mut scale_decode::visitor::types::Composite<'scale, 'info, R>,
337 type_id: R::TypeId,
338 ) -> Result<Self::Value<'scale, 'info>, Self::Error> {
339 Ok(Value {
340 value: ValueDef::Composite(visit_composite::<R, F>(value)?),
341 context: F::context_from_type_id(&type_id),
342 })
343 }
344}
345
346fn visit_composite<R, F>(
348 value: &mut scale_decode::visitor::types::Composite<'_, '_, R>,
349) -> Result<Composite<F::Output>, DecodeError>
350where
351 R: TypeResolver,
352 F: ContextFromTypeId<R::TypeId>,
353{
354 let len = value.remaining();
355 let named = len > 0 && !value.has_unnamed_fields();
357
358 if named {
359 let mut vals = Vec::with_capacity(len);
360 let mut name = value.peek_name();
361 while let Some(v) = value.decode_item(DecodeValueVisitor::<R, F>::new()) {
362 let v = v?;
363 vals.push((name.expect("all fields should be named; we have checked").to_owned(), v));
364 name = value.peek_name();
366 }
367 Ok(Composite::Named(vals))
368 } else {
369 let mut vals = Vec::with_capacity(len);
370 while let Some(v) = value.decode_item(DecodeValueVisitor::<R, F>::new()) {
371 let v = v?;
372 vals.push(v);
373 }
374 Ok(Composite::Unnamed(vals))
375 }
376}
377
378#[cfg(test)]
379mod test {
380 use super::*;
381 use crate::value;
382 use codec::{Compact, Encode};
383 use scale_info::PortableRegistry;
384
385 fn make_type<T: scale_info::TypeInfo + 'static>() -> (u32, PortableRegistry) {
388 let m = scale_info::MetaType::new::<T>();
389 let mut types = scale_info::Registry::new();
390 let id = types.register_type(&m);
391 let portable_registry: PortableRegistry = types.into();
392
393 (id.id, portable_registry)
394 }
395
396 fn encode_decode_check<T: Encode + scale_info::TypeInfo + 'static>(val: T, exp: Value<()>) {
400 encode_decode_check_explicit_info::<T, _>(val, exp)
401 }
402
403 fn encode_decode_check_explicit_info<Ty: scale_info::TypeInfo + 'static, T: Encode>(
406 val: T,
407 ex: Value<()>,
408 ) {
409 let encoded = val.encode();
410 let encoded = &mut &*encoded;
411
412 let (id, portable_registry) = make_type::<Ty>();
413
414 let val = decode_value_as_type(encoded, id, &portable_registry).expect("decoding failed");
416 assert_eq!(val.remove_context(), ex, "decoded value does not look like what we expected");
418 assert_eq!(encoded.len(), 0, "decoding did not consume all of the encoded bytes");
420 }
421
422 #[test]
423 fn decode_primitives() {
424 encode_decode_check(true, Value::bool(true));
425 encode_decode_check(false, Value::bool(false));
426 encode_decode_check_explicit_info::<char, _>('a' as u32, Value::char('a'));
427 encode_decode_check("hello", Value::string("hello"));
428 encode_decode_check(
429 "hello".to_string(), Value::string("hello"),
431 );
432 encode_decode_check(123u8, Value::u128(123));
433 encode_decode_check(123u16, Value::u128(123));
434 encode_decode_check(123u32, Value::u128(123));
435 encode_decode_check(123u64, Value::u128(123));
436 encode_decode_check(123u128, Value::u128(123));
437 encode_decode_check(123i8, Value::i128(123));
443 encode_decode_check(123i16, Value::i128(123));
444 encode_decode_check(123i32, Value::i128(123));
445 encode_decode_check(123i64, Value::i128(123));
446 encode_decode_check(123i128, Value::i128(123));
447 }
453
454 #[test]
455 fn decode_compact_primitives() {
456 encode_decode_check(Compact(123u8), Value::u128(123));
457 encode_decode_check(Compact(123u16), Value::u128(123));
458 encode_decode_check(Compact(123u32), Value::u128(123));
459 encode_decode_check(Compact(123u64), Value::u128(123));
460 encode_decode_check(Compact(123u128), Value::u128(123));
461 }
462
463 #[test]
464 fn decode_compact_named_wrapper_struct() {
465 #[derive(Encode, scale_info::TypeInfo)]
467 struct MyWrapper {
468 inner: u32,
469 }
470 impl From<Compact<MyWrapper>> for MyWrapper {
471 fn from(val: Compact<MyWrapper>) -> MyWrapper {
472 val.0
473 }
474 }
475 impl codec::CompactAs for MyWrapper {
476 type As = u32;
477
478 fn encode_as(&self) -> &Self::As {
479 &self.inner
480 }
481 fn decode_from(inner: Self::As) -> Result<Self, codec::Error> {
482 Ok(MyWrapper { inner })
483 }
484 }
485
486 encode_decode_check(
487 Compact(MyWrapper { inner: 123 }),
488 Value::named_composite(vec![("inner", Value::u128(123))]),
489 );
490 }
491
492 #[test]
493 fn decode_compact_unnamed_wrapper_struct() {
494 #[derive(Encode, scale_info::TypeInfo)]
496 struct MyWrapper(u32);
497 impl From<Compact<MyWrapper>> for MyWrapper {
498 fn from(val: Compact<MyWrapper>) -> MyWrapper {
499 val.0
500 }
501 }
502 impl codec::CompactAs for MyWrapper {
503 type As = u32;
504
505 fn encode_as(&self) -> &Self::As {
511 &self.0
512 }
513 fn decode_from(inner: Self::As) -> Result<Self, codec::Error> {
514 Ok(MyWrapper(inner))
515 }
516 }
517
518 encode_decode_check(
519 Compact(MyWrapper(123)),
520 Value::unnamed_composite(vec![Value::u128(123)]),
521 );
522 }
523
524 #[test]
525 fn decode_sequence_array_tuple_types() {
526 encode_decode_check(vec![1i32, 2, 3], value!((1, 2, 3)));
527 encode_decode_check(
528 [1i32, 2, 3], Value::unnamed_composite(vec![Value::i128(1), Value::i128(2), Value::i128(3)]),
530 );
531 encode_decode_check(
532 (1i32, true, 123456u128),
533 Value::unnamed_composite(vec![Value::i128(1), Value::bool(true), Value::u128(123456)]),
534 );
535 }
536
537 #[test]
538 fn decode_variant_types() {
539 #[derive(Encode, scale_info::TypeInfo)]
540 enum MyEnum {
541 Foo(bool),
542 Bar { hi: String, other: u128 },
543 }
544
545 encode_decode_check(
546 MyEnum::Foo(true),
547 Value::unnamed_variant("Foo", vec![Value::bool(true)]),
548 );
549 encode_decode_check(
550 MyEnum::Bar { hi: "hello".to_string(), other: 123 },
551 value!(Bar { hi: "hello", other: 123u32 }),
552 );
553 }
554
555 #[test]
556 fn decode_composite_types() {
557 #[derive(Encode, scale_info::TypeInfo)]
558 struct Unnamed(bool, String, Vec<u8>);
559
560 #[derive(Encode, scale_info::TypeInfo)]
561 struct Named {
562 is_valid: bool,
563 name: String,
564 bytes: Vec<u8>,
565 }
566
567 encode_decode_check(
568 Unnamed(true, "James".into(), vec![1, 2, 3]),
569 value!((true, "James", (1u8, 2u8, 3u8))),
570 );
571 encode_decode_check(
572 Named { is_valid: true, name: "James".into(), bytes: vec![1, 2, 3] },
573 value!({is_valid: true, name: "James", bytes: (1u8, 2u8, 3u8)}),
574 );
575 }
576
577 #[test]
578 fn decoding_zero_length_composites_always_unnamed() {
579 #[derive(Encode, scale_info::TypeInfo)]
582 struct Named {}
583 #[derive(Encode, scale_info::TypeInfo)]
584 struct Unnamed();
585
586 encode_decode_check(Unnamed(), Value::unnamed_composite(vec![]));
587 encode_decode_check(Named {}, Value::unnamed_composite(vec![]));
588 }
589
590 #[test]
591 fn decode_bit_sequence() {
592 use scale_bits::bits;
593
594 encode_decode_check(bits![0, 1, 1, 0, 1, 0], Value::bit_sequence(bits![0, 1, 1, 0, 1, 0]));
596 }
597
598 #[test]
599 fn decode_composite_fields() {
600 use codec::Encode;
601 use scale_decode::DecodeAsFields;
602
603 #[derive(Encode, scale_decode::DecodeAsType, scale_info::TypeInfo)]
604 struct Foo {
605 a: String,
606 b: bool,
607 c: u16,
608 }
609
610 let (id, types) = make_type::<Foo>();
612 let scale_info::TypeDef::Composite(c) = &types.resolve(id).unwrap().type_def else {
613 panic!("Couldn't get fields");
614 };
615 let mut fields = c.fields.iter().map(|f| scale_decode::Field::new(f.ty.id, f.name));
616
617 let foo = Foo { a: "Hello".to_owned(), b: true, c: 123 };
619 let foo_bytes = foo.encode();
620 let foo_bytes_cursor = &mut &*foo_bytes;
621
622 let out = Composite::decode_as_fields(foo_bytes_cursor, &mut fields, &types)
624 .expect("can decode as fields")
625 .map_context(|_| ());
626 assert_eq!(
627 out,
628 Composite::named([
629 ("a", Value::string("Hello")),
630 ("b", Value::bool(true)),
631 ("c", Value::u128(123))
632 ])
633 );
634 assert_eq!(foo_bytes_cursor.len(), 0, "all bytes should have been consumed");
635 }
636}