more_fps/
non_zero_decimal.rs

1use rust_decimal::Decimal;
2
3#[derive(Debug, PartialEq, Clone, Copy)]
4pub struct NonZeroDecimal(Decimal);
5
6impl NonZeroDecimal {
7    pub fn try_new<T>(value: T) -> Option<Self>
8    where
9        T: TryInto<Decimal>,
10    {
11        let value = value.try_into().ok()?;
12        if value == Decimal::ZERO {
13            None
14        } else {
15            Some(Self(value))
16        }
17    }
18
19    pub fn get(&self) -> &Decimal {
20        &self.0
21    }
22}
23
24impl std::ops::Deref for NonZeroDecimal {
25    type Target = Decimal;
26    fn deref(&self) -> &Self::Target {
27        &self.0
28    }
29}
30
31impl TryFrom<&str> for NonZeroDecimal {
32    type Error = rust_decimal::Error;
33    fn try_from(s: &str) -> Result<Self, Self::Error> {
34        let decimal = Decimal::from_str_exact(s)?;
35        Ok(Self(decimal))
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[test]
44    fn non_zero_decimal() {
45        assert_eq!(
46            NonZeroDecimal::try_new(12).map(|d| d.get().clone()),
47            Some(Decimal::from_str_exact("12").unwrap())
48        );
49    }
50    #[test]
51    fn zero_decimal() {
52        assert_eq!(NonZeroDecimal::try_new(0), None);
53    }
54}