fixed_decimal/
integer.rs

1// This file is part of ICU4X. For terms of use, please see the file
2// called LICENSE at the top level of the ICU4X source tree
3// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5use core::convert::TryFrom;
6use core::fmt;
7
8use core::str::FromStr;
9
10use crate::Decimal;
11use crate::LimitError;
12use crate::ParseError;
13
14/// A [`FixedInteger`] is a [`Decimal`] with no fractional part.
15///
16///
17/// # Examples
18///
19/// ```
20/// # use std::str::FromStr;
21/// use fixed_decimal::Decimal;
22/// use fixed_decimal::FixedInteger;
23/// use fixed_decimal::LimitError;
24///
25/// assert_eq!(Decimal::from(FixedInteger::from(5)), Decimal::from(5));
26/// assert_eq!(
27///     FixedInteger::try_from(Decimal::from(5)),
28///     Ok(FixedInteger::from(5))
29/// );
30/// assert_eq!(
31///     FixedInteger::try_from(Decimal::from_str("05").unwrap()),
32///     Ok(FixedInteger::from_str("05").unwrap())
33/// );
34/// assert_eq!(
35///     FixedInteger::try_from(Decimal::from_str("5.0").unwrap()),
36///     Err(LimitError)
37/// );
38/// ```
39#[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}