radix_common/data/manifest/
definitions.rs

1use vec_traits::vec_decode_with_nice_error;
2
3use crate::internal_prelude::*;
4
5pub use crate::constants::MANIFEST_SBOR_V1_MAX_DEPTH;
6pub use crate::constants::MANIFEST_SBOR_V1_PAYLOAD_PREFIX;
7
8pub type ManifestEncoder<'a> = VecEncoder<'a, ManifestCustomValueKind>;
9pub type ManifestDecoder<'a> = VecDecoder<'a, ManifestCustomValueKind>;
10pub type ManifestValueKind = ValueKind<ManifestCustomValueKind>;
11pub type ManifestValue = Value<ManifestCustomValueKind, ManifestCustomValue>;
12pub type ManifestEnumVariantValue = EnumVariantValue<ManifestCustomValueKind, ManifestCustomValue>;
13pub type ManifestTraverser<'a> = VecTraverser<'a, ManifestCustomTraversal>;
14
15pub trait ManifestCategorize: Categorize<ManifestCustomValueKind> {}
16impl<T: Categorize<ManifestCustomValueKind> + ?Sized> ManifestCategorize for T {}
17
18pub trait ManifestSborEnum: SborEnum<ManifestCustomValueKind> {}
19impl<T: SborEnum<ManifestCustomValueKind> + ?Sized> ManifestSborEnum for T {}
20
21pub trait ManifestSborEnumVariantFor<E: ManifestSborEnum>:
22    SborEnumVariantFor<E, ManifestCustomValueKind>
23{
24}
25impl<E: ManifestSborEnum, T: SborEnumVariantFor<E, ManifestCustomValueKind> + ?Sized>
26    ManifestSborEnumVariantFor<E> for T
27{
28}
29
30pub trait ManifestSborTuple: SborTuple<ManifestCustomValueKind> {}
31impl<T: SborTuple<ManifestCustomValueKind> + ?Sized> ManifestSborTuple for T {}
32
33pub trait ManifestDecode: for<'a> Decode<ManifestCustomValueKind, ManifestDecoder<'a>> {}
34impl<T: for<'a> Decode<ManifestCustomValueKind, ManifestDecoder<'a>>> ManifestDecode for T {}
35
36pub trait ManifestEncode: for<'a> Encode<ManifestCustomValueKind, ManifestEncoder<'a>> {}
37impl<T: for<'a> Encode<ManifestCustomValueKind, ManifestEncoder<'a>> + ?Sized> ManifestEncode
38    for T
39{
40}
41
42pub struct ManifestArgs(crate::data::manifest::ManifestValue, usize);
43
44impl ManifestArgs {
45    pub fn new_from_tuple_or_panic(value: ManifestValue) -> Self {
46        let length = match &value {
47            Value::Tuple { fields } => fields.len(),
48            _ => {
49                panic!("ManifestArgs has to be a Tuple");
50            }
51        };
52        Self(value, length)
53    }
54}
55
56impl Categorize<ManifestCustomValueKind> for ManifestArgs {
57    #[inline]
58    fn value_kind() -> ValueKind<ManifestCustomValueKind> {
59        ValueKind::Tuple
60    }
61}
62
63impl SborTuple<ManifestCustomValueKind> for ManifestArgs {
64    fn get_length(&self) -> usize {
65        self.1
66    }
67}
68
69impl<'a> Encode<ManifestCustomValueKind, ManifestEncoder<'a>> for ManifestArgs {
70    #[inline]
71    fn encode_value_kind(&self, encoder: &mut ManifestEncoder<'a>) -> Result<(), EncodeError> {
72        self.0.encode_value_kind(encoder)
73    }
74
75    #[inline]
76    fn encode_body(&self, encoder: &mut ManifestEncoder<'a>) -> Result<(), EncodeError> {
77        self.0.encode_body(encoder)
78    }
79}
80
81impl From<ManifestArgs> for ManifestValue {
82    fn from(value: ManifestArgs) -> Self {
83        value.0
84    }
85}
86
87#[derive(Debug, Clone, PartialEq, Eq)]
88pub enum RustToManifestValueError {
89    DecodeError(DecodeError),
90    EncodeError(EncodeError),
91}
92
93#[derive(Debug, Clone, PartialEq, Eq)]
94pub enum ManifestToRustValueError {
95    DecodeError(DecodeError),
96    EncodeError(EncodeError),
97}
98
99pub fn manifest_encode<T: ManifestEncode + ?Sized>(value: &T) -> Result<Vec<u8>, EncodeError> {
100    manifest_encode_with_depth_limit(value, MANIFEST_SBOR_V1_MAX_DEPTH)
101}
102
103pub fn manifest_encode_with_depth_limit<T: ManifestEncode + ?Sized>(
104    value: &T,
105    depth_limit: usize,
106) -> Result<Vec<u8>, EncodeError> {
107    let mut buf = Vec::with_capacity(512);
108    let encoder = ManifestEncoder::new(&mut buf, depth_limit);
109    encoder.encode_payload(value, MANIFEST_SBOR_V1_PAYLOAD_PREFIX)?;
110    Ok(buf)
111}
112
113pub fn manifest_decode<T: ManifestDecode>(buf: &[u8]) -> Result<T, DecodeError> {
114    manifest_decode_with_depth_limit(buf, MANIFEST_SBOR_V1_MAX_DEPTH)
115}
116
117pub fn manifest_decode_with_depth_limit<T: ManifestDecode>(
118    buf: &[u8],
119    depth_limit: usize,
120) -> Result<T, DecodeError> {
121    ManifestDecoder::new(buf, depth_limit).decode_payload(MANIFEST_SBOR_V1_PAYLOAD_PREFIX)
122}
123
124/// Decodes a data structure from a byte array.
125///
126/// If an error occurs, the type's schema is exported and used to give a better error message.
127///
128/// NOTE:
129/// * The error path runs very slowly. This should only be used where errors are NOT expected.
130/// * This should not be used where the size of compiled code is an issue, as it will pull
131///   in the schema aggregation code which is large.
132pub fn manifest_decode_with_nice_error<T: ManifestDecode + ScryptoDescribe>(
133    buf: &[u8],
134) -> Result<T, String> {
135    vec_decode_with_nice_error::<ManifestCustomExtension, T>(buf, MANIFEST_SBOR_V1_MAX_DEPTH)
136}
137
138/// Decodes a data structure from a byte array.
139///
140/// If an error occurs, the type's schema is exported and used to give a better error message.
141///
142/// NOTE:
143/// * The error path runs very slowly. This should only be used where errors are NOT expected.
144/// * This should not be used where the size of compiled code is an issue, as it will pull
145///   in the schema aggregation code which is large.
146pub fn manifest_decode_with_depth_limit_and_nice_error<T: ManifestDecode + ScryptoDescribe>(
147    buf: &[u8],
148    depth_limit: usize,
149) -> Result<T, String> {
150    vec_decode_with_nice_error::<ManifestCustomExtension, T>(buf, depth_limit)
151}
152
153pub fn to_manifest_value<T: ManifestEncode + ?Sized>(
154    value: &T,
155) -> Result<ManifestValue, RustToManifestValueError> {
156    let encoded = manifest_encode(value).map_err(RustToManifestValueError::EncodeError)?;
157
158    manifest_decode(&encoded).map_err(RustToManifestValueError::DecodeError)
159}
160
161pub fn from_manifest_value<T: ManifestDecode>(
162    manifest_value: &ManifestValue,
163) -> Result<T, ManifestToRustValueError> {
164    let encoded = manifest_encode(manifest_value).map_err(ManifestToRustValueError::EncodeError)?;
165
166    manifest_decode(&encoded).map_err(ManifestToRustValueError::DecodeError)
167}
168
169#[cfg(test)]
170mod tests {
171    use super::*;
172
173    #[test]
174    fn test_manifest_value_conversions() {
175        let invalid_value = ManifestValue::Tuple {
176            fields: vec![ManifestValue::Array {
177                element_value_kind: ValueKind::U8,
178                elements: vec![
179                    ManifestValue::U8 { value: 1 },
180                    ManifestValue::U16 { value: 2 },
181                ],
182            }],
183        };
184        assert_matches!(
185            to_manifest_value(&invalid_value),
186            Err(RustToManifestValueError::EncodeError(
187                EncodeError::MismatchingArrayElementValueKind { .. }
188            ))
189        );
190
191        let invalid_value = ManifestValue::Map {
192            key_value_kind: ValueKind::U8,
193            value_value_kind: ValueKind::I8,
194            entries: vec![(
195                ManifestValue::U16 { value: 1 },
196                ManifestValue::I8 { value: 1 },
197            )],
198        };
199        assert_matches!(
200            to_manifest_value(&invalid_value),
201            Err(RustToManifestValueError::EncodeError(
202                EncodeError::MismatchingMapKeyValueKind { .. }
203            ))
204        );
205
206        let invalid_value = ManifestValue::Map {
207            key_value_kind: ValueKind::U8,
208            value_value_kind: ValueKind::I8,
209            entries: vec![(
210                ManifestValue::U8 { value: 1 },
211                ManifestValue::I16 { value: 1 },
212            )],
213        };
214        assert_matches!(
215            to_manifest_value(&invalid_value),
216            Err(RustToManifestValueError::EncodeError(
217                EncodeError::MismatchingMapValueValueKind { .. }
218            ))
219        );
220
221        let too_deep_tuple = get_tuple_of_depth(MANIFEST_SBOR_V1_MAX_DEPTH + 1).unwrap();
222        assert_matches!(
223            to_manifest_value(&too_deep_tuple),
224            Err(RustToManifestValueError::EncodeError(
225                EncodeError::MaxDepthExceeded { .. }
226            ))
227        );
228
229        let fine_tuple = get_tuple_of_depth(MANIFEST_SBOR_V1_MAX_DEPTH).unwrap();
230        assert!(to_manifest_value(&fine_tuple).is_ok());
231    }
232
233    pub fn get_tuple_of_depth(depth: usize) -> Option<ManifestValue> {
234        // Minimum tuple depth is 2
235        if depth <= 1 {
236            None
237        } else if depth <= 2 {
238            Some(ManifestValue::Tuple {
239                fields: vec![ManifestValue::U8 { value: 1 }],
240            })
241        } else {
242            let value = get_tuple_of_depth(depth - 1).unwrap();
243            Some(ManifestValue::Tuple {
244                fields: vec![value],
245            })
246        }
247    }
248}