radix_common/data/manifest/model/
manifest_decimal.rs

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