scale_value/scale_impls/
decode.rs

1// Copyright (C) 2022-2023 Parity Technologies (UK) Ltd. (admin@parity.io)
2// This file is a part of the scale-value crate.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//         http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use core::marker::PhantomData;
17
18use crate::prelude::*;
19use crate::value_type::{Composite, Primitive, Value, ValueDef, Variant};
20use scale_decode::{FieldIter, TypeResolver};
21
22// This is emitted if something goes wrong decoding into a Value.
23pub use scale_decode::visitor::DecodeError;
24
25/// A visitor that can be used to decode types into [`Value`]s.
26pub type ValueVisitor<Resolver> = DecodeValueVisitor<Resolver, TypeIdContext>;
27
28/// Attempt to decode some SCALE encoded bytes into a value, by providing a pointer
29/// to the bytes (which will be moved forwards as bytes are used in the decoding),
30/// a type ID, and a type registry from which we'll look up the relevant type information.
31pub 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
48/// Decode data into a [`Composite`] according to a series of fields.
49/// Each field contains a type id and optionally a field name.
50pub 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    // Build a Composite type to pass to a one-off visitor:
60    let mut composite = scale_decode::visitor::types::Composite::new(
61        core::iter::empty(),
62        input,
63        fields,
64        types,
65        false,
66    );
67    // Decode into a Composite value from this:
68    let val = visit_composite::<R, TypeIdContext>(&mut composite)?;
69    // Consume remaining bytes and update input cursor:
70    composite.skip_decoding()?;
71    *input = composite.bytes_from_undecoded();
72    Ok(val)
73}
74
75// Sequences, Tuples and Arrays all have the same methods, so decode them in the same way:
76macro_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
90// We can't implement this on `Value<TypeId>` because we have no TypeId to assign to the value.
91impl 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        // Build a Composite type to pass to a one-off visitor:
98        let mut composite = scale_decode::visitor::types::Composite::new(
99            core::iter::empty(),
100            input,
101            fields,
102            types,
103            false,
104        );
105        // Decode into a Composite value from this:
106        let val = visit_composite::<R, EmptyContext>(&mut composite);
107        // Consume remaining bytes and update input cursor:
108        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    // Note: the DefaultMapper just removes all type ids here.
116    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
124/// We can use [`DecodeValueVisitor`] to decode values, but have two cases to handle:
125///
126/// - We need to be able to decode into [`Value<()>`] for our [`scale_decode::IntoVisitor`]
127///   implementation above (because that trait is agnostic over which visitor is used, and thus
128///   can't have any knowledge on the TypeId type).
129/// - We need to be able to decode into [`Value<TypeId>`] via the [`decode_value_as_type`] fn
130///   above.
131///
132/// This trait basically allows us to handle each case by having a function that is given a
133/// `TypeId` and decides whether to hand back `()` or the `TypeId`.
134pub trait ContextFromTypeId<TypeId> {
135    type Output;
136    fn context_from_type_id(type_id: &TypeId) -> Self::Output;
137}
138
139/// Return () for our value context.
140pub struct EmptyContext;
141impl<TypeId> ContextFromTypeId<TypeId> for EmptyContext {
142    type Output = ();
143    fn context_from_type_id(_type_id: &TypeId) {}
144}
145
146/// Return the type ID for our value context.
147pub 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
155/// A [`scale_decode::Visitor`] implementation for decoding into [`Value`]s.
156pub 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
346/// Extract a named/unnamed Composite type out of scale_decode's Composite.
347fn 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    // if no fields, we'll always assume unnamed.
356    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            // get the next field name now we've decoded one.
365            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    /// Given a type definition, return the PortableType and PortableRegistry
386    /// that our decode functions expect.
387    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    /// Given a value to encode, and a representation of the decoded value, check that our decode functions
397    /// successfully decodes the type to the expected value, based on the implicit SCALE type info that the type
398    /// carries
399    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    /// Given a value to encode, a type to decode it back into, and a representation of
404    /// the decoded value, check that our decode functions successfully decodes as expected.
405    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        // Can we decode?
415        let val = decode_value_as_type(encoded, id, &portable_registry).expect("decoding failed");
416        // Is the decoded value what we expected?
417        assert_eq!(val.remove_context(), ex, "decoded value does not look like what we expected");
418        // Did decoding consume all of the encoded bytes, as expected?
419        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(), // String or &str (above) decode OK
430            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        //// Todo [jsdw]: Can we test this if we need a TypeInfo param?:
438        // encode_decode_check_explicit_info(
439        //     [123u8; 32], // Anything 32 bytes long will do here
440        //     Value::u256([123u8; 32]),
441        // );
442        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        //// Todo [jsdw]: Can we test this if we need a TypeInfo param?:
448        // encode_decode_check_explicit_info(
449        //     [123u8; 32], // Anything 32 bytes long will do here
450        //     Value::i256([123u8; 32]),
451        // );
452    }
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        // A struct that can be compact encoded:
466        #[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        // A struct that can be compact encoded:
495        #[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            // Node the requirement to return something with a lifetime tied
506            // to self here. This means that we can't implement this for things
507            // more complex than wrapper structs (eg `Foo(u32,u32,u32,u32)`) without
508            // shenanigans, meaning that (hopefully) supporting wrapper struct
509            // decoding and nothing fancier is sufficient.
510            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], // compile-time length known
529            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        // The scale-info repr is just a composite, so we don't really track
580        // whether the thing was named or not. either Value will convert back ok anyway.
581        #[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        // scale-decode already tests this more thoroughly:
595        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        // Get the fields we want to decode:
611        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        // get some bytes to decode from:
618        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        // Decode and check that things line up:
623        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}