1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use crate::data::manifest::model::*;
use crate::internal_prelude::*;

#[cfg(feature = "radix_engine_fuzzing")]
use arbitrary::Arbitrary;

#[cfg_attr(feature = "radix_engine_fuzzing", derive(Arbitrary))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ManifestCustomValue {
    Address(ManifestAddress),
    Bucket(ManifestBucket),
    Proof(ManifestProof),
    Expression(ManifestExpression),
    Blob(ManifestBlobRef),
    Decimal(ManifestDecimal),
    PreciseDecimal(ManifestPreciseDecimal),
    NonFungibleLocalId(ManifestNonFungibleLocalId),
    AddressReservation(ManifestAddressReservation),
}

impl CustomValue<ManifestCustomValueKind> for ManifestCustomValue {
    fn get_custom_value_kind(&self) -> ManifestCustomValueKind {
        match self {
            ManifestCustomValue::Address(_) => ManifestCustomValueKind::Address,
            ManifestCustomValue::Bucket(_) => ManifestCustomValueKind::Bucket,
            ManifestCustomValue::Proof(_) => ManifestCustomValueKind::Proof,
            ManifestCustomValue::Expression(_) => ManifestCustomValueKind::Expression,
            ManifestCustomValue::Blob(_) => ManifestCustomValueKind::Blob,
            ManifestCustomValue::Decimal(_) => ManifestCustomValueKind::Decimal,
            ManifestCustomValue::PreciseDecimal(_) => ManifestCustomValueKind::PreciseDecimal,
            ManifestCustomValue::NonFungibleLocalId(_) => {
                ManifestCustomValueKind::NonFungibleLocalId
            }
            ManifestCustomValue::AddressReservation(_) => {
                ManifestCustomValueKind::AddressReservation
            }
        }
    }
}

impl<E: Encoder<ManifestCustomValueKind>> Encode<ManifestCustomValueKind, E>
    for ManifestCustomValue
{
    fn encode_value_kind(&self, encoder: &mut E) -> Result<(), EncodeError> {
        match self {
            ManifestCustomValue::Address(_) => {
                encoder.write_value_kind(ValueKind::Custom(ManifestCustomValueKind::Address))
            }
            ManifestCustomValue::Bucket(_) => {
                encoder.write_value_kind(ValueKind::Custom(ManifestCustomValueKind::Bucket))
            }
            ManifestCustomValue::Proof(_) => {
                encoder.write_value_kind(ValueKind::Custom(ManifestCustomValueKind::Proof))
            }
            ManifestCustomValue::Expression(_) => {
                encoder.write_value_kind(ValueKind::Custom(ManifestCustomValueKind::Expression))
            }
            ManifestCustomValue::Blob(_) => {
                encoder.write_value_kind(ValueKind::Custom(ManifestCustomValueKind::Blob))
            }
            ManifestCustomValue::Decimal(_) => {
                encoder.write_value_kind(ValueKind::Custom(ManifestCustomValueKind::Decimal))
            }
            ManifestCustomValue::PreciseDecimal(_) => {
                encoder.write_value_kind(ValueKind::Custom(ManifestCustomValueKind::PreciseDecimal))
            }
            ManifestCustomValue::NonFungibleLocalId(_) => encoder.write_value_kind(
                ValueKind::Custom(ManifestCustomValueKind::NonFungibleLocalId),
            ),
            ManifestCustomValue::AddressReservation(_) => encoder.write_value_kind(
                ValueKind::Custom(ManifestCustomValueKind::AddressReservation),
            ),
        }
    }

    fn encode_body(&self, encoder: &mut E) -> Result<(), EncodeError> {
        match self {
            // TODO: vector free
            ManifestCustomValue::Address(v) => v.encode_body(encoder),
            ManifestCustomValue::Bucket(v) => v.encode_body(encoder),
            ManifestCustomValue::Proof(v) => v.encode_body(encoder),
            ManifestCustomValue::Expression(v) => v.encode_body(encoder),
            ManifestCustomValue::Blob(v) => v.encode_body(encoder),
            ManifestCustomValue::Decimal(v) => v.encode_body(encoder),
            ManifestCustomValue::PreciseDecimal(v) => v.encode_body(encoder),
            ManifestCustomValue::NonFungibleLocalId(v) => v.encode_body(encoder),
            ManifestCustomValue::AddressReservation(v) => v.encode_body(encoder),
        }
    }
}

impl<D: Decoder<ManifestCustomValueKind>> Decode<ManifestCustomValueKind, D>
    for ManifestCustomValue
{
    fn decode_body_with_value_kind(
        decoder: &mut D,
        value_kind: ValueKind<ManifestCustomValueKind>,
    ) -> Result<Self, DecodeError> {
        match value_kind {
            ValueKind::Custom(cti) => match cti {
                ManifestCustomValueKind::Address => {
                    ManifestAddress::decode_body_with_value_kind(decoder, value_kind)
                        .map(Self::Address)
                }
                ManifestCustomValueKind::Blob => {
                    ManifestBlobRef::decode_body_with_value_kind(decoder, value_kind)
                        .map(Self::Blob)
                }
                ManifestCustomValueKind::Bucket => {
                    ManifestBucket::decode_body_with_value_kind(decoder, value_kind)
                        .map(Self::Bucket)
                }
                ManifestCustomValueKind::Proof => {
                    ManifestProof::decode_body_with_value_kind(decoder, value_kind).map(Self::Proof)
                }
                ManifestCustomValueKind::Expression => {
                    ManifestExpression::decode_body_with_value_kind(decoder, value_kind)
                        .map(Self::Expression)
                }
                ManifestCustomValueKind::Decimal => {
                    ManifestDecimal::decode_body_with_value_kind(decoder, value_kind)
                        .map(Self::Decimal)
                }
                ManifestCustomValueKind::PreciseDecimal => {
                    ManifestPreciseDecimal::decode_body_with_value_kind(decoder, value_kind)
                        .map(Self::PreciseDecimal)
                }
                ManifestCustomValueKind::NonFungibleLocalId => {
                    ManifestNonFungibleLocalId::decode_body_with_value_kind(decoder, value_kind)
                        .map(Self::NonFungibleLocalId)
                }
                ManifestCustomValueKind::AddressReservation => {
                    ManifestAddressReservation::decode_body_with_value_kind(decoder, value_kind)
                        .map(Self::AddressReservation)
                }
            },
            _ => Err(DecodeError::UnexpectedCustomValueKind {
                actual: value_kind.as_u8(),
            }),
        }
    }
}