radix_common/data/manifest/model/
manifest_address.rs

1use crate::data::manifest::ManifestCustomValueKind;
2use crate::types::EntityType;
3use crate::types::NodeId;
4use crate::*;
5
6use sbor::rust::fmt;
7use sbor::*;
8
9/// Any address supported by manifest, both global and local.
10///
11/// Must start with a supported entity type byte.
12#[cfg_attr(
13    feature = "fuzzing",
14    derive(::arbitrary::Arbitrary, ::serde::Serialize, ::serde::Deserialize)
15)]
16#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
17#[must_use]
18pub enum ManifestAddress {
19    /// Static address, either global or internal, with entity type byte checked.
20    /// TODO: prevent direct construction, as in `NonFungibleLocalId`
21    Static(NodeId),
22    /// Named address, global only at the moment.
23    Named(ManifestNamedAddress),
24}
25
26impl ManifestAddress {
27    pub fn named(id: u32) -> Self {
28        Self::Named(ManifestNamedAddress(id))
29    }
30
31    pub fn into_named(self) -> Option<ManifestNamedAddress> {
32        match self {
33            ManifestAddress::Static(_) => None,
34            ManifestAddress::Named(named) => Some(named),
35        }
36    }
37}
38
39#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, ManifestSbor)]
40#[sbor(
41    as_type = "ManifestAddress",
42    as_ref = "&ManifestAddress::Named(*self)",
43    from_value = "value.into_named().ok_or(DecodeError::InvalidCustomValue)?"
44)]
45#[cfg_attr(
46    feature = "fuzzing",
47    derive(::arbitrary::Arbitrary, ::serde::Serialize, ::serde::Deserialize)
48)]
49pub struct ManifestNamedAddress(pub u32);
50
51pub const MANIFEST_ADDRESS_DISCRIMINATOR_STATIC: u8 = 0u8;
52pub const MANIFEST_ADDRESS_DISCRIMINATOR_NAMED: u8 = 1u8;
53
54impl From<ManifestNamedAddress> for ManifestAddress {
55    fn from(value: ManifestNamedAddress) -> Self {
56        Self::Named(value)
57    }
58}
59
60//========
61// binary
62//========
63
64impl Categorize<ManifestCustomValueKind> for ManifestAddress {
65    #[inline]
66    fn value_kind() -> ValueKind<ManifestCustomValueKind> {
67        ValueKind::Custom(ManifestCustomValueKind::Address)
68    }
69}
70
71impl<E: Encoder<ManifestCustomValueKind>> Encode<ManifestCustomValueKind, E> for ManifestAddress {
72    #[inline]
73    fn encode_value_kind(&self, encoder: &mut E) -> Result<(), EncodeError> {
74        encoder.write_value_kind(Self::value_kind())
75    }
76
77    #[inline]
78    fn encode_body(&self, encoder: &mut E) -> Result<(), EncodeError> {
79        match self {
80            Self::Static(node_id) => {
81                encoder.write_discriminator(MANIFEST_ADDRESS_DISCRIMINATOR_STATIC)?;
82                encoder.write_slice(node_id.as_bytes())?;
83            }
84            Self::Named(address_id) => {
85                encoder.write_discriminator(MANIFEST_ADDRESS_DISCRIMINATOR_NAMED)?;
86                encoder.write_slice(&address_id.0.to_le_bytes())?;
87            }
88        }
89        Ok(())
90    }
91}
92
93impl<D: Decoder<ManifestCustomValueKind>> Decode<ManifestCustomValueKind, D> for ManifestAddress {
94    fn decode_body_with_value_kind(
95        decoder: &mut D,
96        value_kind: ValueKind<ManifestCustomValueKind>,
97    ) -> Result<Self, DecodeError> {
98        decoder.check_preloaded_value_kind(value_kind, Self::value_kind())?;
99        match decoder.read_discriminator()? {
100            MANIFEST_ADDRESS_DISCRIMINATOR_STATIC => {
101                let slice = decoder.read_slice(NodeId::LENGTH)?;
102                if EntityType::from_repr(slice[0]).is_none() {
103                    return Err(DecodeError::InvalidCustomValue);
104                }
105                Ok(Self::Static(NodeId(slice.try_into().unwrap())))
106            }
107            MANIFEST_ADDRESS_DISCRIMINATOR_NAMED => {
108                let slice = decoder.read_slice(4)?;
109                let id = u32::from_le_bytes(slice.try_into().unwrap());
110                Ok(Self::Named(ManifestNamedAddress(id)))
111            }
112            _ => Err(DecodeError::InvalidCustomValue),
113        }
114    }
115}
116
117//======
118// text
119//======
120
121impl fmt::Debug for ManifestAddress {
122    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
123        match self {
124            ManifestAddress::Static(node_id) => {
125                write!(f, "Address({})", hex::encode(node_id.as_bytes()))
126            }
127            ManifestAddress::Named(name) => write!(f, "{name:?}"),
128        }
129    }
130}
131
132impl fmt::Debug for ManifestNamedAddress {
133    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
134        write!(f, "NamedAddress({})", self.0)
135    }
136}
137
138#[cfg(test)]
139mod tests {
140    use super::*;
141    use crate::internal_prelude::*;
142    #[cfg(feature = "alloc")]
143    use sbor::prelude::Vec;
144
145    fn prepare_address(
146        addr_input: &(impl ManifestEncode + Debug),
147    ) -> Result<ManifestAddress, sbor::DecodeError> {
148        #[cfg(not(feature = "alloc"))]
149        println!("Encoding manifest address: {:?}", addr_input);
150        let mut buf = Vec::new();
151        let mut encoder = VecEncoder::<ManifestCustomValueKind>::new(&mut buf, 1);
152        assert!(addr_input.encode_body(&mut encoder).is_ok());
153        let mut decoder = VecDecoder::<ManifestCustomValueKind>::new(&buf, 1);
154        decoder.decode_deeper_body_with_value_kind::<ManifestAddress>(ManifestAddress::value_kind())
155    }
156
157    #[test]
158    fn manifest_address_decode_static_success() {
159        let node_id = NodeId::new(EntityType::GlobalPackage as u8, &[0; NodeId::RID_LENGTH]);
160        let addr_input = ManifestAddress::Static(node_id);
161        let addr_output = prepare_address(&addr_input);
162        assert!(addr_output.is_ok());
163        assert_eq!(addr_input, addr_output.unwrap());
164    }
165
166    #[test]
167    fn manifest_address_decode_named_success() {
168        let addr_input = ManifestAddress::named(1);
169        let addr_input2 = ManifestNamedAddress(1);
170        let addr_output = prepare_address(&addr_input);
171        let addr_output2 = prepare_address(&addr_input2);
172        assert!(addr_output.is_ok());
173        assert_eq!(addr_input, addr_output.unwrap());
174        assert_eq!(addr_input, addr_output2.unwrap());
175    }
176
177    #[test]
178    fn manifest_address_decode_static_fail() {
179        // use invalid entity type (0) to an generate error
180        let node_id = NodeId::new(0, &[0; NodeId::RID_LENGTH]);
181        let addr_input = ManifestAddress::Static(node_id);
182        let addr_output = prepare_address(&addr_input);
183        assert_matches!(addr_output, Err(DecodeError::InvalidCustomValue));
184    }
185
186    #[test]
187    fn manifest_address_decode_named_fail() {
188        let mut buf = Vec::new();
189        let mut encoder = VecEncoder::<ManifestCustomValueKind>::new(&mut buf, 1);
190        encoder
191            .write_discriminator(MANIFEST_ADDRESS_DISCRIMINATOR_NAMED)
192            .unwrap();
193        let malformed_value: u8 = 1; // use u8 instead of u32 should inovke an error
194        encoder.write_slice(&malformed_value.to_le_bytes()).unwrap();
195
196        let mut decoder = VecDecoder::<ManifestCustomValueKind>::new(&buf, 1);
197        let addr_output = decoder
198            .decode_deeper_body_with_value_kind::<ManifestAddress>(ManifestAddress::value_kind());
199
200        // expecting 4 bytes, found only 1, so Buffer Underflow error should occur
201        assert_matches!(addr_output, Err(DecodeError::BufferUnderflow { .. }));
202    }
203
204    #[test]
205    fn manifest_address_decode_discriminator_fail() {
206        let mut buf = Vec::new();
207        let mut encoder = VecEncoder::<ManifestCustomValueKind>::new(&mut buf, 1);
208        // use invalid discriminator value
209        encoder.write_discriminator(0xff).unwrap();
210
211        let mut decoder = VecDecoder::<ManifestCustomValueKind>::new(&buf, 1);
212        let addr_output = decoder
213            .decode_deeper_body_with_value_kind::<ManifestAddress>(ManifestAddress::value_kind());
214
215        assert_matches!(addr_output, Err(DecodeError::InvalidCustomValue));
216    }
217}