frame_decode/methods/
custom_value_decoder.rs1use crate::methods::custom_value_type_info::{
17 CustomValueInfo, CustomValueInfoError, CustomValueTypeInfo,
18};
19use crate::utils::{DecodeErrorTrace, decode_with_error_tracing};
20use alloc::vec::Vec;
21use scale_type_resolver::TypeResolver;
22
23#[non_exhaustive]
25#[allow(missing_docs)]
26#[derive(Clone, Debug, thiserror::Error)]
27pub enum CustomValueDecodeError<TypeId> {
28 #[error("Cannot get custom value info: {0}")]
29 CannotGetInfo(CustomValueInfoError),
30 #[error("Cannot decode custom value: {reason}")]
31 CannotDecodeValue {
32 ty: TypeId,
33 reason: DecodeErrorTrace,
34 },
35 #[error("There were leftover bytes attempting to decode the custom value")]
36 LeftoverBytes { bytes: Vec<u8> },
37}
38
39pub fn decode_custom_value<'info, 'resolver, Info, Resolver, V>(
41 name: &str,
42 info: &'info Info,
43 type_resolver: &'resolver V::TypeResolver,
44 visitor: V,
45) -> Result<V::Value<'info, 'resolver>, CustomValueDecodeError<Info::TypeId>>
46where
47 Info: CustomValueTypeInfo,
48 Info::TypeId: Clone + core::fmt::Debug,
49 Resolver: TypeResolver<TypeId = Info::TypeId>,
50 V: scale_decode::Visitor<TypeResolver = Resolver>,
51 V::Error: core::fmt::Debug,
52{
53 let info = info
54 .custom_value_info(name)
55 .map_err(CustomValueDecodeError::CannotGetInfo)?;
56
57 decode_custom_value_with_info(&info, type_resolver, visitor)
58}
59
60pub fn decode_custom_value_with_info<'info, 'resolver, V>(
62 info: &CustomValueInfo<'info, <V::TypeResolver as TypeResolver>::TypeId>,
63 type_resolver: &'resolver V::TypeResolver,
64 visitor: V,
65) -> Result<
66 V::Value<'info, 'resolver>,
67 CustomValueDecodeError<<V::TypeResolver as TypeResolver>::TypeId>,
68>
69where
70 V: scale_decode::Visitor,
71 V::Error: core::fmt::Debug,
72{
73 let type_id = info.type_id.clone();
74 let cursor = &mut &*info.bytes;
75
76 let value = decode_with_error_tracing(cursor, type_id.clone(), type_resolver, visitor)
77 .map_err(|e| CustomValueDecodeError::CannotDecodeValue {
78 ty: type_id,
79 reason: e,
80 })?;
81
82 if !cursor.is_empty() {
83 Err(CustomValueDecodeError::LeftoverBytes {
84 bytes: cursor.to_vec(),
85 })
86 } else {
87 Ok(value)
88 }
89}