radix_common/data/manifest/model/
manifest_precise_decimal.rs1use 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#[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
41impl 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 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 assert_matches!(dec_output, Err(DecodeError::BufferUnderflow { .. }));
113 }
114}