radix_common/data/scrypto/
definitions.rs

1use vec_traits::vec_decode_with_nice_error;
2
3use crate::internal_prelude::*;
4
5pub use crate::constants::SCRYPTO_SBOR_V1_MAX_DEPTH;
6pub use crate::constants::SCRYPTO_SBOR_V1_PAYLOAD_PREFIX;
7
8pub type ScryptoEncoder<'a> = VecEncoder<'a, ScryptoCustomValueKind>;
9pub type ScryptoDecoder<'a> = VecDecoder<'a, ScryptoCustomValueKind>;
10pub type ScryptoTraverser<'a> = VecTraverser<'a, ScryptoCustomTraversal>;
11pub type ScryptoValueKind = ValueKind<ScryptoCustomValueKind>;
12pub type ScryptoValue = Value<ScryptoCustomValueKind, ScryptoCustomValue>;
13// ScryptoRawValue and friends are defined in custom_payload_wrappers.rs
14
15// The following trait "aliases" are to be used in parameters.
16//
17// They are much nicer to read than the underlying traits, but because they are "new", and are defined
18// via blanket impls, they can only be used for parameters, but cannot be used for implementations.
19//
20// Implementations should instead implement the underlying traits:
21// * Categorize<ScryptoCustomValueKind>
22// * Encode<ScryptoCustomValueKind, E> (impl over all E: Encoder<ScryptoCustomValueKind>)
23// * Decode<ScryptoCustomValueKind, D> (impl over all D: Decoder<ScryptoCustomValueKind>)
24//
25// TODO: Change these to be Trait aliases once stable in rust: https://github.com/rust-lang/rust/issues/41517
26pub trait ScryptoCategorize: Categorize<ScryptoCustomValueKind> {}
27impl<T: Categorize<ScryptoCustomValueKind> + ?Sized> ScryptoCategorize for T {}
28
29pub trait ScryptoSborEnum: SborEnum<ScryptoCustomValueKind> {}
30impl<T: SborEnum<ScryptoCustomValueKind> + ?Sized> ScryptoSborEnum for T {}
31
32pub trait ScryptoSborEnumVariantFor<E: ScryptoSborEnum>:
33    SborEnumVariantFor<E, ScryptoCustomValueKind>
34{
35}
36impl<E: ScryptoSborEnum, T: SborEnumVariantFor<E, ScryptoCustomValueKind> + ?Sized>
37    ScryptoSborEnumVariantFor<E> for T
38{
39}
40
41pub trait ScryptoSborTuple: SborTuple<ScryptoCustomValueKind> {}
42impl<T: SborTuple<ScryptoCustomValueKind> + ?Sized> ScryptoSborTuple for T {}
43
44pub trait ScryptoDecode: for<'a> Decode<ScryptoCustomValueKind, ScryptoDecoder<'a>> {}
45impl<T: for<'a> Decode<ScryptoCustomValueKind, ScryptoDecoder<'a>>> ScryptoDecode for T {}
46
47pub trait ScryptoEncode: for<'a> Encode<ScryptoCustomValueKind, ScryptoEncoder<'a>> {}
48impl<T: for<'a> Encode<ScryptoCustomValueKind, ScryptoEncoder<'a>> + ?Sized> ScryptoEncode for T {}
49
50pub trait ScryptoDescribe: Describe<ScryptoCustomTypeKind> {}
51impl<T: Describe<ScryptoCustomTypeKind>> ScryptoDescribe for T {}
52
53pub trait ScryptoSbor: ScryptoCategorize + ScryptoDecode + ScryptoEncode + ScryptoDescribe {}
54impl<T: ScryptoCategorize + ScryptoDecode + ScryptoEncode + ScryptoDescribe> ScryptoSbor for T {}
55
56/// Encodes a data structure into byte array.
57pub fn scrypto_encode<T: ScryptoEncode + ?Sized>(value: &T) -> Result<Vec<u8>, EncodeError> {
58    scrypto_encode_with_depth_limit(value, SCRYPTO_SBOR_V1_MAX_DEPTH)
59}
60
61pub fn scrypto_encode_with_depth_limit<T: ScryptoEncode + ?Sized>(
62    value: &T,
63    depth_limit: usize,
64) -> Result<Vec<u8>, EncodeError> {
65    let mut buf = Vec::with_capacity(512);
66    let encoder = ScryptoEncoder::new(&mut buf, depth_limit);
67    encoder.encode_payload(value, SCRYPTO_SBOR_V1_PAYLOAD_PREFIX)?;
68    Ok(buf)
69}
70
71/// Decodes a data structure from a byte array.
72pub fn scrypto_decode<T: ScryptoDecode>(buf: &[u8]) -> Result<T, DecodeError> {
73    scrypto_decode_with_depth_limit(buf, SCRYPTO_SBOR_V1_MAX_DEPTH)
74}
75
76pub fn scrypto_decode_with_depth_limit<T: ScryptoDecode>(
77    buf: &[u8],
78    depth_limit: usize,
79) -> Result<T, DecodeError> {
80    ScryptoDecoder::new(buf, depth_limit).decode_payload(SCRYPTO_SBOR_V1_PAYLOAD_PREFIX)
81}
82
83/// Decodes a data structure from a byte array.
84///
85/// If an error occurs, the type's schema is exported and used to give a better error message.
86///
87/// NOTE:
88/// * The error path runs very slowly. This should only be used where errors are NOT expected.
89/// * This should not be used in Scrypto, as it will pull in the schema aggregation code which is large.
90pub fn scrypto_decode_with_nice_error<T: ScryptoDecode + ScryptoDescribe>(
91    buf: &[u8],
92) -> Result<T, String> {
93    vec_decode_with_nice_error::<ScryptoCustomExtension, T>(buf, SCRYPTO_SBOR_V1_MAX_DEPTH)
94}
95
96/// Decodes a data structure from a byte array.
97///
98/// If an error occurs, the type's schema is exported and used to give a better error message.
99///
100/// NOTE:
101/// * The error path runs very slowly. This should only be used where errors are NOT expected.
102/// * This should not be used in Scrypto, as it will pull in the schema aggregation code which is large.
103pub fn scrypto_decode_with_depth_limit_and_nice_error<T: ScryptoDecode + ScryptoDescribe>(
104    buf: &[u8],
105    depth_limit: usize,
106) -> Result<T, String> {
107    vec_decode_with_nice_error::<ScryptoCustomExtension, T>(buf, depth_limit)
108}