radix_common/data/manifest/model/
manifest_precise_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::PreciseDecimal;
10use crate::*;
11
12pub const PRECISE_DECIMAL_SIZE: usize = PreciseDecimal::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 ManifestPreciseDecimal(pub [u8; PRECISE_DECIMAL_SIZE]);
20
21//========
22// error
23//========
24
25/// Represents an error when parsing ManifestPreciseDecimal.
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub enum ParseManifestPreciseDecimalError {
28    InvalidLength,
29}
30
31#[cfg(not(feature = "alloc"))]
32impl std::error::Error for ParseManifestPreciseDecimalError {}
33
34#[cfg(not(feature = "alloc"))]
35impl fmt::Display for ParseManifestPreciseDecimalError {
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 ManifestPreciseDecimal {
46    type Error = ParseManifestPreciseDecimalError;
47
48    fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
49        if slice.len() != PRECISE_DECIMAL_SIZE {
50            return Err(Self::Error::InvalidLength);
51        }
52        Ok(Self(copy_u8_array(slice)))
53    }
54}
55
56impl ManifestPreciseDecimal {
57    pub fn to_vec(&self) -> Vec<u8> {
58        self.0.to_vec()
59    }
60}
61
62manifest_type!(
63    ManifestPreciseDecimal,
64    ManifestCustomValueKind::PreciseDecimal,
65    PRECISE_DECIMAL_SIZE,
66);
67scrypto_describe_for_manifest_type!(
68    ManifestPreciseDecimal,
69    PRECISE_DECIMAL_TYPE,
70    precise_decimal_type_data,
71);
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76    use crate::internal_prelude::*;
77
78    #[test]
79    fn manifest_precise_decimal_parse_fail() {
80        let buf = Vec::from_iter(0u8..PRECISE_DECIMAL_SIZE as u8);
81
82        let dec = ManifestPreciseDecimal(buf.as_slice().try_into().unwrap());
83        let mut dec_vec = dec.to_vec();
84
85        assert!(ManifestPreciseDecimal::try_from(dec_vec.as_slice()).is_ok());
86
87        // malform encoded vector
88        dec_vec.push(0);
89        let dec_out = ManifestPreciseDecimal::try_from(dec_vec.as_slice());
90        assert_matches!(
91            dec_out,
92            Err(ParseManifestPreciseDecimalError::InvalidLength)
93        );
94
95        #[cfg(not(feature = "alloc"))]
96        println!("Manifest Precise Decimal error: {}", dec_out.unwrap_err());
97    }
98
99    #[test]
100    fn manifest_precise_decimal_encode_decode_fail() {
101        let mut buf = Vec::new();
102        let mut encoder = VecEncoder::<ManifestCustomValueKind>::new(&mut buf, 1);
103        let malformed_value: u8 = 0;
104        encoder.write_slice(&malformed_value.to_le_bytes()).unwrap();
105
106        let mut decoder = VecDecoder::<ManifestCustomValueKind>::new(&buf, 1);
107        let dec_output = decoder.decode_deeper_body_with_value_kind::<ManifestPreciseDecimal>(
108            ManifestPreciseDecimal::value_kind(),
109        );
110
111        // expecting 4 bytes, found only 1, so Buffer Underflow error should occur
112        assert_matches!(dec_output, Err(DecodeError::BufferUnderflow { .. }));
113    }
114}