1use core::convert::TryFrom;
6use core::fmt;
7
8use core::str::FromStr;
9
10use crate::Decimal;
11use crate::LimitError;
12use crate::ParseError;
13
14#[derive(Debug, Clone, PartialEq, Default)]
40pub struct FixedInteger(Decimal);
41
42impl From<FixedInteger> for Decimal {
43 fn from(value: FixedInteger) -> Self {
44 value.0
45 }
46}
47
48macro_rules! impl_fixed_integer_from_integer_type {
49 ($type:ident) => {
50 impl From<$type> for FixedInteger {
51 fn from(value: $type) -> Self {
52 FixedInteger(Decimal::from(value))
53 }
54 }
55 };
56}
57
58impl_fixed_integer_from_integer_type!(isize);
59impl_fixed_integer_from_integer_type!(i128);
60impl_fixed_integer_from_integer_type!(i64);
61impl_fixed_integer_from_integer_type!(i32);
62impl_fixed_integer_from_integer_type!(i16);
63impl_fixed_integer_from_integer_type!(i8);
64impl_fixed_integer_from_integer_type!(usize);
65impl_fixed_integer_from_integer_type!(u128);
66impl_fixed_integer_from_integer_type!(u64);
67impl_fixed_integer_from_integer_type!(u32);
68impl_fixed_integer_from_integer_type!(u16);
69impl_fixed_integer_from_integer_type!(u8);
70
71impl writeable::Writeable for FixedInteger {
72 fn write_to<W: fmt::Write + ?Sized>(&self, sink: &mut W) -> fmt::Result {
73 self.0.write_to(sink)
74 }
75}
76
77impl TryFrom<Decimal> for FixedInteger {
78 type Error = LimitError;
79 fn try_from(signed_fd: Decimal) -> Result<Self, Self::Error> {
80 if signed_fd.absolute.magnitude_range().start() != &0 {
81 Err(LimitError)
82 } else {
83 Ok(FixedInteger(signed_fd))
84 }
85 }
86}
87
88impl FixedInteger {
89 #[inline]
90 pub fn try_from_str(s: &str) -> Result<Self, ParseError> {
91 Self::try_from_utf8(s.as_bytes())
92 }
93
94 pub fn try_from_utf8(code_units: &[u8]) -> Result<Self, ParseError> {
95 FixedInteger::try_from(Decimal::try_from_utf8(code_units)?)
96 .map_err(|LimitError| ParseError::Limit)
97 }
98}
99
100impl FromStr for FixedInteger {
101 type Err = ParseError;
102 #[inline]
103 fn from_str(s: &str) -> Result<Self, Self::Err> {
104 Self::try_from_str(s)
105 }
106}