scale_value/scale_impls/
encode.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 crate::prelude::*;
17use crate::value_type::{Composite, Primitive, Value, ValueDef, Variant};
18use codec::{Compact, Encode};
19use scale_bits::Bits;
20use scale_decode::TypeResolver;
21use scale_encode::error::ErrorKind;
22use scale_encode::{error::Kind, EncodeAsFields, EncodeAsType, Error};
23use scale_encode::{
24    Composite as EncodeComposite, CompositeField, FieldIter, Variant as EncodeVariant,
25};
26
27impl<T> EncodeAsType for Value<T> {
28    fn encode_as_type_to<R: TypeResolver>(
29        &self,
30        type_id: R::TypeId,
31        types: &R,
32        out: &mut Vec<u8>,
33    ) -> Result<(), Error> {
34        match &self.value {
35            ValueDef::Composite(val) => encode_composite(val, type_id, types, out),
36            ValueDef::Variant(val) => encode_variant(val, type_id, types, out),
37            ValueDef::Primitive(val) => encode_primitive(val, type_id, types, out),
38            ValueDef::BitSequence(val) => encode_bitsequence(val, type_id, types, out),
39        }
40    }
41}
42
43impl<T> EncodeAsFields for Value<T> {
44    fn encode_as_fields_to<R: TypeResolver>(
45        &self,
46        fields: &mut dyn FieldIter<'_, R::TypeId>,
47        types: &R,
48        out: &mut Vec<u8>,
49    ) -> Result<(), Error> {
50        match &self.value {
51            ValueDef::Composite(composite) => composite.encode_as_fields_to(fields, types, out),
52            _ => Err(Error::custom_str("Cannot encode non-composite Value shape into fields")),
53        }
54    }
55}
56
57impl<T> EncodeAsFields for Composite<T> {
58    fn encode_as_fields_to<R: TypeResolver>(
59        &self,
60        fields: &mut dyn FieldIter<'_, R::TypeId>,
61        types: &R,
62        out: &mut Vec<u8>,
63    ) -> Result<(), Error> {
64        match self {
65            Composite::Named(vals) => {
66                let keyvals =
67                    vals.iter().map(|(key, val)| (Some(&**key), CompositeField::new(val)));
68                EncodeComposite::new(keyvals).encode_composite_fields_to(fields, types, out)
69            }
70            Composite::Unnamed(vals) => {
71                let vals = vals.iter().map(|val| (None, CompositeField::new(val)));
72                EncodeComposite::new(vals).encode_composite_fields_to(fields, types, out)
73            }
74        }
75    }
76}
77
78// A scale-value composite type can represent sequences, arrays, composites and tuples. `scale_encode`'s Composite helper
79// can't handle encoding to sequences/arrays. However, we can encode safely into sequences here because we can inspect the
80// values we have and more safely skip newtype wrappers without also skipping through types that might represent 1-value
81// sequences/arrays for instance.
82fn encode_composite<T, R: TypeResolver>(
83    value: &Composite<T>,
84    mut type_id: R::TypeId,
85    types: &R,
86    out: &mut Vec<u8>,
87) -> Result<(), Error> {
88    // Encode our composite Value as-is (pretty much; we will try to
89    // unwrap the Value only if we need primitives).
90    fn do_encode_composite<T, R: TypeResolver>(
91        value: &Composite<T>,
92        type_id: R::TypeId,
93        types: &R,
94        out: &mut Vec<u8>,
95    ) -> Result<(), Error> {
96        // context to hand to visitor functions:
97        let ctx = (type_id.clone(), out);
98
99        let visit_composite_or_tuple =
100            |(type_id, out): (R::TypeId, &mut Vec<u8>)| -> Result<(), Error> {
101                match value {
102                    Composite::Named(vals) => {
103                        let keyvals =
104                            vals.iter().map(|(key, val)| (Some(&**key), CompositeField::new(val)));
105                        EncodeComposite::new(keyvals)
106                            .encode_composite_as_type_to(type_id, types, out)
107                    }
108                    Composite::Unnamed(vals) => {
109                        let vals = vals.iter().map(|val| (None, CompositeField::new(val)));
110                        EncodeComposite::new(vals).encode_composite_as_type_to(type_id, types, out)
111                    }
112                }
113            };
114
115        let visitor = scale_type_resolver::visitor::new::<
116            '_,
117            (R::TypeId, &mut Vec<u8>),
118            R::TypeId,
119            Result<(), Error>,
120            _,
121        >(ctx, |(type_id, out), _| {
122            let mut values = value.values();
123            match (values.next(), values.next()) {
124                // Exactly one value:
125                (Some(value), None) => value.encode_as_type_to(type_id, types, out),
126                // Some other number of values:
127                _ => Err(Error::new(ErrorKind::WrongShape {
128                    actual: Kind::Tuple,
129                    expected_id: format!("{:?}", type_id),
130                })),
131            }
132        })
133        .visit_composite(|ctx, _, _| visit_composite_or_tuple(ctx))
134        .visit_tuple(|ctx, _| visit_composite_or_tuple(ctx))
135        .visit_sequence(|(_, out), _path, type_id| {
136            // sequences start with compact encoded length:
137            Compact(value.len() as u32).encode_to(out);
138            match value {
139                Composite::Named(named_vals) => {
140                    for (name, val) in named_vals {
141                        val.encode_as_type_to(type_id.clone(), types, out)
142                            .map_err(|e| e.at_field(name.to_string()))?;
143                    }
144                }
145                Composite::Unnamed(vals) => {
146                    for (idx, val) in vals.iter().enumerate() {
147                        val.encode_as_type_to(type_id.clone(), types, out)
148                            .map_err(|e| e.at_idx(idx))?;
149                    }
150                }
151            }
152            Ok(())
153        })
154        .visit_array(|(_, out), type_id, array_len| {
155            if value.len() != array_len {
156                return Err(Error::new(ErrorKind::WrongLength {
157                    actual_len: value.len(),
158                    expected_len: array_len,
159                }));
160            }
161            for (idx, val) in value.values().enumerate() {
162                val.encode_as_type_to(type_id.clone(), types, out).map_err(|e| e.at_idx(idx))?;
163            }
164            Ok(())
165        })
166        .visit_bit_sequence(|(_, out), store, order| {
167            let format = scale_bits::Format { store, order };
168            encode_vals_to_bitsequence(value.values(), out, format)
169        });
170
171        match types.resolve_type(type_id, visitor) {
172            Ok(Ok(())) => Ok(()),
173            Ok(Err(err)) => Err(err),
174            Err(err) => Err(Error::new(ErrorKind::TypeResolvingError(format!("{:?}", err)))),
175        }
176    }
177
178    // First, try and encode everything as-is, only writing to the output
179    // bytes if the encoding is actually successful. This means that if the
180    // Value provided matches the structure of the TypeInfo exactly, things
181    // should always work.
182    let original_error = {
183        let mut temp_out = Vec::new();
184        match do_encode_composite(value, type_id.clone(), types, &mut temp_out) {
185            Ok(()) => {
186                out.extend_from_slice(&temp_out);
187                return Ok(());
188            }
189            Err(e) => e,
190        }
191    };
192
193    // Next, unwrap any newtype wrappers from our TypeInfo and try again. If we
194    // can unwrap, then try to encode our Value to this immediately (this will work
195    // if the Value provided already ignored all newtype wrappers). If we have nothing
196    // to unwrap then ignore this extra encode attempt.
197    {
198        let (inner_type_id, inner_is_different) =
199            find_single_entry_with_same_repr::<R>(type_id.clone(), types);
200        if inner_is_different {
201            let mut temp_out = Vec::new();
202            if let Ok(()) = do_encode_composite(value, inner_type_id.clone(), types, &mut temp_out)
203            {
204                out.extend_from_slice(&temp_out);
205                return Ok(());
206            }
207            type_id = inner_type_id;
208        }
209    }
210
211    // Peel off a single layer from the provided Value (if it appears to be new-type-esque,
212    // ie contains just one value) to see if, after doing so, the thing can be successfully
213    // encoded. The inner `.encode_as_type_to` will loop around and peel off another layer
214    // etc if no luck. Ultimately we'll just return the original error below if this all
215    // fails.
216    if let Some(value) = get_only_value_from_composite(value) {
217        let mut temp_out = Vec::new();
218        if let Ok(()) = value.encode_as_type_to(type_id.clone(), types, &mut temp_out) {
219            out.extend_from_slice(&temp_out);
220            return Ok(());
221        }
222    }
223
224    // return the original error we got back if none of the above is succcessful.
225    Err(original_error)
226}
227
228/// Skip into the target type past any newtype wrapper like things.
229/// Also returns a bool indicating whether we skipped into something or not.
230/// This bool is true when the returned id is different from the id that was passed in.
231fn find_single_entry_with_same_repr<R: TypeResolver>(
232    type_id: R::TypeId,
233    types: &R,
234) -> (R::TypeId, bool) {
235    fn do_find<R: TypeResolver>(
236        type_id: R::TypeId,
237        types: &R,
238        type_id_has_changed: bool,
239    ) -> (R::TypeId, bool) {
240        let ctx = (type_id.clone(), type_id_has_changed);
241        let visitor = scale_type_resolver::visitor::new(ctx.clone(), |ctx, _| ctx)
242            .visit_tuple(|return_unchanged, fields| {
243                if fields.len() == 1 {
244                    let ty = fields.next().expect("has 1 item; qed;");
245                    do_find(ty, types, true)
246                } else {
247                    return_unchanged
248                }
249            })
250            .visit_composite(|return_unchanged, _, fields| {
251                if fields.len() == 1 {
252                    let ty = fields.next().expect("has 1 item; qed;").id;
253                    do_find(ty, types, true)
254                } else {
255                    return_unchanged
256                }
257            })
258            .visit_array(
259                |return_unchanged, ty_id, len| {
260                    if len == 1 {
261                        do_find(ty_id, types, true)
262                    } else {
263                        return_unchanged
264                    }
265                },
266            );
267        types.resolve_type(type_id, visitor).unwrap_or(ctx)
268    }
269    do_find(type_id, types, false)
270}
271
272// if the composite type has exactly one value, return that Value, else return None.
273fn get_only_value_from_composite<T>(value: &'_ Composite<T>) -> Option<&'_ Value<T>> {
274    let mut values = value.values();
275    match (values.next(), values.next()) {
276        (Some(value), None) => Some(value),
277        _ => None,
278    }
279}
280
281// It's likely that people will use a composite to represen bit sequences,
282// so support encoding to them in this way too.
283fn encode_vals_to_bitsequence<'a, T: 'a>(
284    vals: impl ExactSizeIterator<Item = &'a Value<T>>,
285    out: &mut Vec<u8>,
286    format: scale_bits::Format,
287) -> Result<(), Error> {
288    let mut bools = Vec::with_capacity(vals.len());
289    for (idx, value) in vals.enumerate() {
290        if let Some(v) = value.as_bool() {
291            // support turning (true, false, true, true, false) into a bit sequence.
292            bools.push(v);
293        } else if let Some(v) = value.as_u128() {
294            // support turning (1, 0, 1, 1, 0) into a bit sequence.
295            if v == 0 || v == 1 {
296                bools.push(v == 1)
297            } else {
298                return Err(Error::custom_str(
299                    "Cannot encode non-boolean/0/1 value into a bit sequence entry",
300                )
301                .at_idx(idx));
302            }
303        } else if let Some(v) = value.as_i128() {
304            // support turning (1, 0, 1, 1, 0) into a bit sequence (if the number's are not unsigned it's still fine).
305            if v == 0 || v == 1 {
306                bools.push(v == 1)
307            } else {
308                return Err(Error::custom_str(
309                    "Cannot encode non-boolean/0/1 value into a bit sequence entry",
310                )
311                .at_idx(idx));
312            }
313        } else {
314            // anything else is an error.
315            return Err(Error::custom_str(
316                "Cannot encode non-boolean/0/1 value into a bit sequence entry",
317            )
318            .at_idx(idx));
319        }
320    }
321
322    scale_bits::encode_using_format_to(bools.into_iter(), format, out);
323    Ok(())
324}
325
326fn encode_variant<T, R: TypeResolver>(
327    value: &Variant<T>,
328    type_id: R::TypeId,
329    types: &R,
330    out: &mut Vec<u8>,
331) -> Result<(), Error> {
332    match &value.values {
333        Composite::Named(vals) => {
334            let keyvals = vals.iter().map(|(key, val)| (Some(&**key), CompositeField::new(val)));
335            EncodeVariant { name: &value.name, fields: EncodeComposite::new(keyvals) }
336                .encode_variant_as_type_to(type_id, types, out)
337        }
338        Composite::Unnamed(vals) => {
339            let vals = vals.iter().map(|val| (None, CompositeField::new(val)));
340            EncodeVariant { name: &value.name, fields: EncodeComposite::new(vals) }
341                .encode_variant_as_type_to(type_id, types, out)
342        }
343    }
344}
345
346fn encode_primitive<R: TypeResolver>(
347    value: &Primitive,
348    type_id: R::TypeId,
349    types: &R,
350    bytes: &mut Vec<u8>,
351) -> Result<(), Error> {
352    match value {
353        Primitive::Bool(val) => val.encode_as_type_to(type_id, types, bytes),
354        Primitive::Char(val) => val.encode_as_type_to(type_id, types, bytes),
355        Primitive::String(val) => val.encode_as_type_to(type_id, types, bytes),
356        Primitive::U128(val) => val.encode_as_type_to(type_id, types, bytes),
357        Primitive::I128(val) => val.encode_as_type_to(type_id, types, bytes),
358        Primitive::U256(val) => val.encode_as_type_to(type_id, types, bytes),
359        Primitive::I256(val) => val.encode_as_type_to(type_id, types, bytes),
360    }
361}
362
363fn encode_bitsequence<R: TypeResolver>(
364    value: &Bits,
365    type_id: R::TypeId,
366    types: &R,
367    bytes: &mut Vec<u8>,
368) -> Result<(), Error> {
369    value.encode_as_type_to(type_id, types, bytes)
370}
371
372#[cfg(test)]
373mod test {
374    use super::*;
375    use crate::value;
376    use codec::{Compact, Encode};
377    use scale_info::PortableRegistry;
378
379    // Panic after some duration.
380    #[cfg(feature = "__std")]
381    fn panic_after<T, F>(d: core::time::Duration, f: F) -> T
382    where
383        T: Send + 'static,
384        F: FnOnce() -> T,
385        F: Send + 'static,
386    {
387        use std::{sync::mpsc, thread};
388
389        let (done_tx, done_rx) = mpsc::channel();
390        let handle = thread::spawn(move || {
391            let val = f();
392            done_tx.send(()).expect("Unable to send completion signal");
393            val
394        });
395
396        match done_rx.recv_timeout(d) {
397            Ok(_) => handle.join().expect("Thread panicked"),
398            Err(_) => panic!("Thread took too long"),
399        }
400    }
401
402    /// Given a type definition, return the PortableType and PortableRegistry
403    /// that our decode functions expect.
404    fn make_type<T: scale_info::TypeInfo + 'static>() -> (u32, PortableRegistry) {
405        let m = scale_info::MetaType::new::<T>();
406        let mut types = scale_info::Registry::new();
407        let id = types.register_type(&m);
408        let portable_registry: PortableRegistry = types.into();
409
410        (id.id, portable_registry)
411    }
412
413    // Attempt to SCALE encode a Value and expect it to match the standard Encode impl for the second param given.
414    fn assert_can_encode_to_type<T: Encode + scale_info::TypeInfo + 'static>(
415        value: Value<()>,
416        ty: T,
417    ) {
418        let expected = ty.encode();
419        let mut buf = Vec::new();
420
421        let (ty_id, types) = make_type::<T>();
422
423        value.encode_as_type_to(ty_id, &types, &mut buf).expect("error encoding value as type");
424        assert_eq!(expected, buf);
425    }
426
427    #[test]
428    fn can_encode_basic_primitive_values() {
429        assert_can_encode_to_type(Value::i128(123), 123i8);
430        assert_can_encode_to_type(Value::i128(123), 123i16);
431        assert_can_encode_to_type(Value::i128(123), 123i32);
432        assert_can_encode_to_type(Value::i128(123), 123i64);
433        assert_can_encode_to_type(Value::i128(123), 123i128);
434
435        assert_can_encode_to_type(Value::u128(123), 123u8);
436        assert_can_encode_to_type(Value::u128(123), 123u16);
437        assert_can_encode_to_type(Value::u128(123), 123u32);
438        assert_can_encode_to_type(Value::u128(123), 123u64);
439        assert_can_encode_to_type(Value::u128(123), 123u128);
440
441        assert_can_encode_to_type(Value::bool(true), true);
442        assert_can_encode_to_type(Value::bool(false), false);
443
444        assert_can_encode_to_type(Value::string("Hello"), "Hello");
445        assert_can_encode_to_type(Value::string("Hello"), "Hello".to_string());
446    }
447
448    #[test]
449    fn chars_encoded_like_numbers() {
450        assert_can_encode_to_type(Value::char('j'), 'j' as u32);
451        assert_can_encode_to_type(Value::char('j'), b'j');
452    }
453
454    #[test]
455    fn can_encode_primitive_arrs_to_array() {
456        use crate::Primitive;
457
458        assert_can_encode_to_type(Value::primitive(Primitive::U256([12u8; 32])), [12u8; 32]);
459        assert_can_encode_to_type(Value::primitive(Primitive::I256([12u8; 32])), [12u8; 32]);
460    }
461
462    #[test]
463    fn can_encode_primitive_arrs_to_vecs() {
464        use crate::Primitive;
465
466        assert_can_encode_to_type(Value::primitive(Primitive::U256([12u8; 32])), vec![12u8; 32]);
467        assert_can_encode_to_type(Value::primitive(Primitive::I256([12u8; 32])), vec![12u8; 32]);
468    }
469
470    #[test]
471    fn can_encode_arrays() {
472        let value = Value::unnamed_composite(vec![
473            Value::u128(1),
474            Value::u128(2),
475            Value::u128(3),
476            Value::u128(4),
477        ]);
478        assert_can_encode_to_type(value, [1u16, 2, 3, 4]);
479    }
480
481    #[test]
482    fn can_encode_variants() {
483        #[derive(Encode, scale_info::TypeInfo)]
484        enum Foo {
485            Named { hello: String, foo: bool },
486            Unnamed(u64, Vec<bool>),
487        }
488
489        let named_value = value!(Named { foo: true, hello: "world" });
490
491        assert_can_encode_to_type(named_value, Foo::Named { hello: "world".into(), foo: true });
492
493        let unnamed_value = value!(Unnamed(123u64, (true, false, true)));
494
495        assert_can_encode_to_type(unnamed_value, Foo::Unnamed(123, vec![true, false, true]));
496    }
497
498    #[test]
499    fn can_encode_vec_tuples() {
500        // Presume we have a type: Vec<(u8, u16)>.
501        let vec_tuple = value!(((20u8, 30u16)));
502
503        assert_can_encode_to_type(vec_tuple, vec![(20u8, 30u16)]);
504    }
505
506    #[test]
507    fn can_encode_structs() {
508        #[derive(Encode, scale_info::TypeInfo)]
509        struct Foo {
510            hello: String,
511            foo: bool,
512        }
513
514        let named_value = value!({foo: true, hello: "world"});
515
516        assert_can_encode_to_type(named_value, Foo { hello: "world".into(), foo: true });
517    }
518
519    #[test]
520    fn can_encode_tuples_from_named_composite() {
521        let named_value = value!({hello: "world", foo: true});
522        assert_can_encode_to_type(named_value, ("world", true));
523    }
524
525    #[test]
526    fn can_encode_tuples_from_unnamed_composite() {
527        let unnamed_value = value!(("world", true));
528        assert_can_encode_to_type(unnamed_value, ("world", true));
529    }
530
531    #[test]
532    fn can_encode_unnamed_composite_to_named_struct() {
533        #[derive(Encode, scale_info::TypeInfo)]
534        struct Foo {
535            hello: String,
536            foo: bool,
537        }
538
539        // This is useful because things like transaction calls are often named composites, but
540        // we just want to be able to provide the correct values as simply as possible without
541        // necessarily knowing the names.
542        let unnamed_value = value!(("world", true));
543        assert_can_encode_to_type(unnamed_value, Foo { hello: "world".to_string(), foo: true });
544    }
545
546    #[test]
547    fn can_encode_bitvecs() {
548        use scale_bits::bits;
549
550        // We have more thorough tests of bitvec encoding in scale-bits.
551        // Here we just do a basic confirmation that bool composites or
552        // bitsequences encode to the bits we'd expect.
553        assert_can_encode_to_type(
554            Value::bit_sequence(bits![0, 1, 1, 0, 0, 1]),
555            bits![0, 1, 1, 0, 0, 1],
556        );
557        // a single value should still encode OK:
558        assert_can_encode_to_type(value!((false)), bits![0]);
559        assert_can_encode_to_type(
560            value!((false, true, true, false, false, true)),
561            bits![0, 1, 1, 0, 0, 1],
562        );
563        assert_can_encode_to_type(value!((0u8, 1u8, 1u8, 0u8, 0u8, 1u8)), bits![0, 1, 1, 0, 0, 1]);
564        assert_can_encode_to_type(value!((0, 1, 1, 0, 0, 1)), bits![0, 1, 1, 0, 0, 1]);
565    }
566
567    #[test]
568    fn can_encode_to_compact_types() {
569        assert_can_encode_to_type(Value::u128(123), Compact(123u64));
570        assert_can_encode_to_type(Value::u128(123), Compact(123u64));
571        assert_can_encode_to_type(Value::u128(123), Compact(123u64));
572        assert_can_encode_to_type(Value::u128(123), Compact(123u64));
573
574        // As a special case, as long as ultimately we have a primitive value, we can compact encode it:
575        assert_can_encode_to_type(value!((123)), Compact(123u64));
576        assert_can_encode_to_type(value!(({foo: 123u64})), Compact(123u64));
577    }
578
579    #[test]
580    fn can_encode_skipping_struct_newtype_wrappers() {
581        // One layer of "newtype" can be ignored:
582        #[derive(Encode, scale_info::TypeInfo)]
583        struct Foo {
584            inner: u32,
585        }
586        assert_can_encode_to_type(Value::u128(32), Foo { inner: 32 });
587
588        // Two layers can be ignored:
589        #[derive(Encode, scale_info::TypeInfo)]
590        struct Bar(Foo);
591        assert_can_encode_to_type(Value::u128(32), Bar(Foo { inner: 32 }));
592        assert_can_encode_to_type(value!((32u8)), Bar(Foo { inner: 32 }));
593
594        // Encoding a Composite to a Composite(Composite) shape is fine too:
595        #[derive(Encode, scale_info::TypeInfo)]
596        struct SomeBytes(Vec<u8>);
597        assert_can_encode_to_type(
598            Value::from_bytes([1, 2, 3, 4, 5]),
599            SomeBytes(vec![1, 2, 3, 4, 5]),
600        );
601        assert_can_encode_to_type(Value::from_bytes([1]), SomeBytes(vec![1]));
602    }
603
604    #[test]
605    fn can_encode_skipping_value_newtype_wrappers() {
606        #[derive(Encode, scale_info::TypeInfo)]
607        struct Foo {
608            inner: u32,
609        }
610
611        // The correct number of layers to match Foo
612        assert_can_encode_to_type(
613            Value::unnamed_composite(vec![Value::u128(32)]),
614            Foo { inner: 32 },
615        );
616        // One layer too many.
617        assert_can_encode_to_type(
618            Value::unnamed_composite(vec![Value::unnamed_composite(vec![Value::u128(32)])]),
619            Foo { inner: 32 },
620        );
621        // Two layers too many.
622        assert_can_encode_to_type(
623            Value::unnamed_composite(vec![Value::unnamed_composite(vec![
624                Value::unnamed_composite(vec![Value::u128(32)]),
625            ])]),
626            Foo { inner: 32 },
627        );
628    }
629
630    // Prior to https://github.com/paritytech/scale-value/pulls/48, this test will take
631    // too long and panic. #48 should ensure that this doesn't happen.
632    #[test]
633    #[cfg(feature = "__std")]
634    fn encoding_shouldnt_take_forever() {
635        panic_after(core::time::Duration::from_millis(100), || {
636            #[derive(scale_info::TypeInfo, codec::Encode)]
637            struct A(bool);
638
639            let mut buf = Vec::new();
640            let (ty_id, types) = make_type::<A>();
641            let value = Value::unnamed_composite(vec![Value::from_bytes(0u32.to_le_bytes())]);
642
643            value
644                .encode_as_type_to(ty_id, &types, &mut buf)
645                .expect_err("We tried encoding a Value of the wrong shape so this should fail");
646        })
647    }
648}