radix_common/data/manifest/model/
manifest_blob.rs

1use crate::internal_prelude::*;
2
3#[cfg_attr(
4    feature = "fuzzing",
5    derive(::arbitrary::Arbitrary, ::serde::Serialize, ::serde::Deserialize)
6)]
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
8pub struct ManifestBlobRef(pub [u8; 32]);
9
10//========
11// error
12//========
13
14/// Represents an error when parsing ManifestBlobRef.
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub enum ParseManifestBlobRefError {
17    InvalidLength,
18}
19
20#[cfg(not(feature = "alloc"))]
21impl std::error::Error for ParseManifestBlobRefError {}
22
23#[cfg(not(feature = "alloc"))]
24impl fmt::Display for ParseManifestBlobRefError {
25    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26        write!(f, "{:?}", self)
27    }
28}
29
30//========
31// binary
32//========
33
34impl TryFrom<&[u8]> for ManifestBlobRef {
35    type Error = ParseManifestBlobRefError;
36
37    fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
38        if slice.len() != 32 {
39            return Err(Self::Error::InvalidLength);
40        }
41        Ok(Self(copy_u8_array(slice)))
42    }
43}
44
45impl ManifestBlobRef {
46    pub fn to_vec(&self) -> Vec<u8> {
47        self.0.to_vec()
48    }
49}
50
51manifest_type!(ManifestBlobRef, ManifestCustomValueKind::Blob, 32);
52
53impl sbor::Describe<ScryptoCustomTypeKind> for ManifestBlobRef {
54    const TYPE_ID: sbor::RustTypeId = <Vec<u8> as Describe<ScryptoCustomTypeKind>>::TYPE_ID;
55
56    fn type_data() -> sbor::TypeData<ScryptoCustomTypeKind, sbor::RustTypeId> {
57        Vec::<u8>::type_data()
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn manifest_blob_parse_fail() {
67        let buf = Vec::from_iter(0..32u8);
68
69        let blob = ManifestBlobRef(buf.as_slice().try_into().unwrap());
70        let mut blob_vec = blob.to_vec();
71
72        assert!(ManifestBlobRef::try_from(blob_vec.as_slice()).is_ok());
73
74        // malform encoded vector
75        blob_vec.push(0);
76        let blob_out = ManifestBlobRef::try_from(blob_vec.as_slice());
77        assert_matches!(blob_out, Err(ParseManifestBlobRefError::InvalidLength));
78
79        #[cfg(not(feature = "alloc"))]
80        println!("Manifest Blob error: {}", blob_out.unwrap_err());
81    }
82
83    #[test]
84    fn manifest_blob_encode_decode_fail() {
85        let mut buf = Vec::new();
86        let mut encoder = VecEncoder::<ManifestCustomValueKind>::new(&mut buf, 1);
87        let malformed_value: u8 = 0;
88        encoder.write_slice(&malformed_value.to_le_bytes()).unwrap();
89
90        let mut decoder = VecDecoder::<ManifestCustomValueKind>::new(&buf, 1);
91        let blob_output = decoder
92            .decode_deeper_body_with_value_kind::<ManifestBlobRef>(ManifestBlobRef::value_kind());
93
94        // expecting 4 bytes, found only 1, so Buffer Underflow error should occur
95        assert_matches!(blob_output, Err(DecodeError::BufferUnderflow { .. }));
96    }
97}