decstr/bitstring/
dynamic.rs

1use crate::{
2    binary::{
3        BinaryBuf,
4        DynamicBinaryBuf,
5    },
6    text::ArrayTextBuf,
7    Error,
8    OverflowError,
9};
10
11#[cfg(test)]
12use crate::binary::encode_max;
13
14/**
15A dynamically sized decimal number with enough precision to fit any Rust primitive number.
16*/
17#[derive(Clone, Copy)]
18pub struct Bitstring(DynamicBinaryBuf<20>);
19
20impl Bitstring {
21    /**
22    Try create a decimal from the given buffer.
23
24    The buffer is assumed to be in little-endian byte-order already.
25    This method will fail if the buffer length is not a multiple of 4 bytes, or it's too
26    big to fit in a `Bitstring`.
27    */
28    pub fn try_from_le_bytes(bytes: &[u8]) -> Result<Self, Error> {
29        if bytes.is_empty() || bytes.len() % 4 != 0 {
30            Err(OverflowError::exact_size_mismatch(
31                bytes.len(),
32                bytes.len() + 4 - (bytes.len() % 4),
33                "decimals must be a multiple of 32 bits (4 bytes)",
34            ))?;
35        }
36
37        let mut buf = DynamicBinaryBuf::try_with_exactly_storage_width_bytes(bytes.len())?;
38
39        buf.bytes_mut().copy_from_slice(bytes);
40
41        Ok(Self(buf))
42    }
43
44    /**
45    Get a reference to the underlying bitstring buffer.
46
47    This buffer is always stored in little-endian byte-order, regardless of the endianness
48    of the platform.
49    */
50    pub fn as_le_bytes(&self) -> &[u8] {
51        // Even on big-endian platforms we always encode numbers in little-endian order
52        self.0.bytes()
53    }
54
55    /**
56    Create a decimal with the finite value zero.
57    */
58    pub fn zero() -> Self {
59        Self::from(0u8)
60    }
61
62    #[cfg(test)]
63    fn max() -> Self {
64        let mut buf = DynamicBinaryBuf::ZERO;
65
66        encode_max(&mut buf, false);
67
68        Self(buf)
69    }
70
71    #[cfg(test)]
72    fn min() -> Self {
73        let mut buf = DynamicBinaryBuf::ZERO;
74
75        encode_max(&mut buf, true);
76
77        Self(buf)
78    }
79}
80
81classify!(Bitstring);
82
83try_s2d!(ArrayTextBuf::<128> => Bitstring);
84d2s!(Bitstring);
85
86f2d!(f32 => from_f32 => Bitstring);
87f2d!(f64 => from_f64 => Bitstring);
88
89try_d2f!(Bitstring => to_f32 => f32);
90try_d2f!(Bitstring => to_f64 => f64);
91
92i2d!(i8 => from_i8 => Bitstring);
93i2d!(i16 => from_i16 => Bitstring);
94i2d!(i32 => from_i32 => Bitstring);
95i2d!(i64 => from_i64 => Bitstring);
96i2d!(i128 => from_i128 => Bitstring);
97
98try_d2i!(Bitstring => to_i8 => i8);
99try_d2i!(Bitstring => to_i16 => i16);
100try_d2i!(Bitstring => to_i32 => i32);
101try_d2i!(Bitstring => to_i64 => i64);
102try_d2i!(Bitstring => to_i128 => i128);
103
104i2d!(u8 => from_u8 => Bitstring);
105i2d!(u16 => from_u16 => Bitstring);
106i2d!(u32 => from_u32 => Bitstring);
107i2d!(u64 => from_u64 => Bitstring);
108i2d!(u128 => from_u128 => Bitstring);
109
110try_d2i!(Bitstring => to_u8 => u8);
111try_d2i!(Bitstring => to_u16 => u16);
112try_d2i!(Bitstring => to_u32 => u32);
113try_d2i!(Bitstring => to_u64 => u64);
114try_d2i!(Bitstring => to_u128 => u128);