radix_common/data/scrypto/
custom_value.rs

1use crate::internal_prelude::*;
2
3#[cfg_attr(feature = "fuzzing", derive(::arbitrary::Arbitrary))]
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum ScryptoCustomValue {
6    Reference(Reference),
7    Own(Own),
8    Decimal(Decimal),
9    PreciseDecimal(PreciseDecimal),
10    NonFungibleLocalId(NonFungibleLocalId),
11}
12
13impl CustomValue<ScryptoCustomValueKind> for ScryptoCustomValue {
14    fn get_custom_value_kind(&self) -> ScryptoCustomValueKind {
15        match self {
16            ScryptoCustomValue::Reference(_) => ScryptoCustomValueKind::Reference,
17            ScryptoCustomValue::Own(_) => ScryptoCustomValueKind::Own,
18            ScryptoCustomValue::Decimal(_) => ScryptoCustomValueKind::Decimal,
19            ScryptoCustomValue::PreciseDecimal(_) => ScryptoCustomValueKind::PreciseDecimal,
20            ScryptoCustomValue::NonFungibleLocalId(_) => ScryptoCustomValueKind::NonFungibleLocalId,
21        }
22    }
23}
24
25impl<E: Encoder<ScryptoCustomValueKind>> Encode<ScryptoCustomValueKind, E> for ScryptoCustomValue {
26    fn encode_value_kind(&self, encoder: &mut E) -> Result<(), EncodeError> {
27        encoder.write_value_kind(ValueKind::Custom(self.get_custom_value_kind()))
28    }
29
30    fn encode_body(&self, encoder: &mut E) -> Result<(), EncodeError> {
31        match self {
32            // TODO: vector free
33            ScryptoCustomValue::Reference(v) => v.encode_body(encoder),
34            ScryptoCustomValue::Own(v) => v.encode_body(encoder),
35            ScryptoCustomValue::Decimal(v) => v.encode_body(encoder),
36            ScryptoCustomValue::PreciseDecimal(v) => v.encode_body(encoder),
37            ScryptoCustomValue::NonFungibleLocalId(v) => v.encode_body(encoder),
38        }
39    }
40}
41
42impl<D: Decoder<ScryptoCustomValueKind>> Decode<ScryptoCustomValueKind, D> for ScryptoCustomValue {
43    fn decode_body_with_value_kind(
44        decoder: &mut D,
45        value_kind: ValueKind<ScryptoCustomValueKind>,
46    ) -> Result<Self, DecodeError> {
47        match value_kind {
48            ValueKind::Custom(cti) => match cti {
49                ScryptoCustomValueKind::Reference => {
50                    Reference::decode_body_with_value_kind(decoder, value_kind).map(Self::Reference)
51                }
52                ScryptoCustomValueKind::Own => {
53                    Own::decode_body_with_value_kind(decoder, value_kind).map(Self::Own)
54                }
55                ScryptoCustomValueKind::Decimal => {
56                    Decimal::decode_body_with_value_kind(decoder, value_kind).map(Self::Decimal)
57                }
58                ScryptoCustomValueKind::PreciseDecimal => {
59                    PreciseDecimal::decode_body_with_value_kind(decoder, value_kind)
60                        .map(Self::PreciseDecimal)
61                }
62                ScryptoCustomValueKind::NonFungibleLocalId => {
63                    NonFungibleLocalId::decode_body_with_value_kind(decoder, value_kind)
64                        .map(Self::NonFungibleLocalId)
65                }
66            },
67            _ => Err(DecodeError::UnexpectedCustomValueKind {
68                actual: value_kind.as_u8(),
69            }),
70        }
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77    use crate::types::NodeId;
78
79    #[test]
80    fn test_custom_types_group1() {
81        let values = (Reference(NodeId([1u8; NodeId::LENGTH])),);
82        let bytes = scrypto_encode(&values).unwrap();
83        assert_eq!(
84            bytes,
85            vec![
86                92, // prefix
87                33, // tuple
88                1,  // length
89                128, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
90                1, 1, 1, 1, // reference
91            ]
92        );
93        assert_eq!(
94            scrypto_decode::<ScryptoValue>(&bytes).unwrap(),
95            ScryptoValue::Tuple {
96                fields: vec![ScryptoValue::Custom {
97                    value: ScryptoCustomValue::Reference(Reference(NodeId([1u8; NodeId::LENGTH]))),
98                },]
99            }
100        );
101    }
102
103    #[test]
104    fn test_custom_types_group2() {
105        let values = (Own(NodeId([1u8; NodeId::LENGTH])),);
106        let bytes = scrypto_encode(&values).unwrap();
107        assert_eq!(
108            bytes,
109            vec![
110                92, // prefix
111                33, // tuple
112                1,  // length
113                144, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
114                1, 1, 1, 1, // own
115            ]
116        );
117        assert_eq!(
118            scrypto_decode::<ScryptoValue>(&bytes).unwrap(),
119            ScryptoValue::Tuple {
120                fields: vec![ScryptoValue::Custom {
121                    value: ScryptoCustomValue::Own(Own(NodeId([1u8; NodeId::LENGTH]))),
122                },]
123            }
124        );
125    }
126
127    #[test]
128    fn test_custom_types_group4() {
129        let values = (
130            Decimal::ONE,
131            PreciseDecimal::ONE,
132            NonFungibleLocalId::integer(1),
133            NonFungibleLocalId::bytes(vec![2, 3]).unwrap(),
134        );
135        let bytes = scrypto_encode(&values).unwrap();
136        assert_eq!(
137            bytes,
138            vec![
139                92, // prefix
140                33, // tuple
141                4,  // length
142                160, 0, 0, 100, 167, 179, 182, 224, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
143                0, 0, // decimal
144                176, 0, 0, 0, 0, 16, 159, 75, 179, 21, 7, 201, 123, 206, 151, 192, 0, 0, 0, 0, 0,
145                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // precise decimal
146                192, 1, 0, 0, 0, 0, 0, 0, 0, 1, // non-fungible local id
147                192, 2, 2, 2, 3 // non-fungible local id
148            ]
149        );
150        assert_eq!(
151            scrypto_decode::<ScryptoValue>(&bytes).unwrap(),
152            ScryptoValue::Tuple {
153                fields: vec![
154                    ScryptoValue::Custom {
155                        value: ScryptoCustomValue::Decimal(Decimal::ONE),
156                    },
157                    ScryptoValue::Custom {
158                        value: ScryptoCustomValue::PreciseDecimal(PreciseDecimal::ONE),
159                    },
160                    ScryptoValue::Custom {
161                        value: ScryptoCustomValue::NonFungibleLocalId(NonFungibleLocalId::integer(
162                            1
163                        )),
164                    },
165                    ScryptoValue::Custom {
166                        value: ScryptoCustomValue::NonFungibleLocalId(
167                            NonFungibleLocalId::bytes(vec![2, 3]).unwrap()
168                        ),
169                    },
170                ]
171            }
172        );
173    }
174}