polyvalue/inner_types/
fixed.rs

1use crate::Error;
2use fpdec::{CheckedAdd, CheckedDiv, CheckedMul, CheckedRem, CheckedSub, Decimal, Round};
3use serde::{Deserialize, Serialize};
4use std::{ops::Deref, str::FromStr};
5
6/// Generates a Fixed from a decimal literal
7///
8/// # Example
9/// ```rust
10/// use polyvalue::{fpdec::Decimal, fixed};
11/// use polyvalue::types::Fixed;
12/// let value = fixed!(1.0);
13/// ```
14#[macro_export]
15macro_rules! fixed {
16    ($value:expr) => {
17        Fixed::from(fpdec::Dec!($value))
18    };
19}
20
21#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone, Serialize, Deserialize, Default)]
22pub struct BoxedDecimal(Box<Decimal>);
23impl BoxedDecimal {
24    pub fn new(value: Decimal) -> Self {
25        Self(Box::new(value))
26    }
27
28    pub fn inner(&self) -> &Decimal {
29        &self.0
30    }
31
32    pub fn inner_mut(&mut self) -> &mut Decimal {
33        &mut self.0
34    }
35
36    pub fn n_frac_digits(&self) -> u8 {
37        self.0.n_frac_digits()
38    }
39
40    pub fn trunc(&self) -> Self {
41        Self::new(self.0.trunc())
42    }
43
44    pub fn coefficient(&self) -> i128 {
45        self.0.coefficient()
46    }
47}
48
49impl From<BoxedDecimal> for f64 {
50    fn from(val: BoxedDecimal) -> Self {
51        (*val.0).into()
52    }
53}
54
55impl From<Decimal> for BoxedDecimal {
56    fn from(value: Decimal) -> Self {
57        Self::new(value)
58    }
59}
60
61impl FromStr for BoxedDecimal {
62    type Err = Error;
63    fn from_str(s: &str) -> Result<Self, Self::Err> {
64        Ok(Self::new(s.parse::<Decimal>()?))
65    }
66}
67
68impl std::fmt::Display for BoxedDecimal {
69    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70        self.0.fmt(f)
71    }
72}
73
74impl std::fmt::Debug for BoxedDecimal {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        self.0.fmt(f)
77    }
78}
79
80impl CheckedAdd for BoxedDecimal {
81    type Output = Option<Self>;
82    fn checked_add(self, rhs: Self) -> Self::Output {
83        self.0.checked_add(*rhs.0).map(Self::new)
84    }
85}
86impl CheckedSub for BoxedDecimal {
87    type Output = Option<Self>;
88    fn checked_sub(self, rhs: Self) -> Self::Output {
89        self.0.checked_sub(*rhs.0).map(Self::new)
90    }
91}
92impl CheckedMul for BoxedDecimal {
93    type Output = Option<Self>;
94    fn checked_mul(self, rhs: Self) -> Self::Output {
95        self.0.checked_mul(*rhs.0).map(Self::new)
96    }
97}
98impl CheckedDiv for BoxedDecimal {
99    type Output = Option<Self>;
100    fn checked_div(self, rhs: Self) -> Self::Output {
101        self.0.checked_div(*rhs.0).map(Self::new)
102    }
103}
104impl CheckedRem for BoxedDecimal {
105    type Output = Option<Self>;
106    fn checked_rem(self, rhs: Self) -> Self::Output {
107        self.0.checked_rem(*rhs.0).map(Self::new)
108    }
109}
110impl Round for BoxedDecimal {
111    fn round(self, n_frac_digits: i8) -> Self {
112        Self::new(self.0.round(n_frac_digits))
113    }
114
115    fn checked_round(self, n_frac_digits: i8) -> Option<Self> {
116        self.0.checked_round(n_frac_digits).map(Self::new)
117    }
118}
119impl std::ops::Neg for BoxedDecimal {
120    type Output = Self;
121    fn neg(self) -> Self::Output {
122        Self::new(-*(self.0))
123    }
124}
125
126impl Deref for BoxedDecimal {
127    type Target = Decimal;
128    fn deref(&self) -> &Self::Target {
129        &self.0
130    }
131}