1use std::fmt;
7use std::ops::{Add, Div, Mul};
8use std::str::FromStr;
9
10use rust_decimal::Decimal;
11use serde::{Deserialize, Deserializer, Serialize, Serializer};
12
13use crate::errors::O2Error;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16pub struct UnsignedDecimal(Decimal);
17
18impl UnsignedDecimal {
19 pub const ONE: Self = Self(Decimal::ONE);
21
22 pub const ZERO: Self = Self(Decimal::ZERO);
24
25 pub fn new(value: Decimal) -> Result<Self, O2Error> {
27 if value.is_sign_negative() && !value.is_zero() {
28 return Err(O2Error::Other(format!(
29 "UnsignedDecimal cannot be negative: {value}"
30 )));
31 }
32 Ok(Self(value))
33 }
34
35 pub fn zero() -> Self {
37 Self(Decimal::ZERO)
38 }
39
40 pub fn try_sub(&self, other: Self) -> Result<Self, O2Error> {
42 Self::new(self.0 - other.0)
43 }
44
45 pub fn inner(&self) -> &Decimal {
47 &self.0
48 }
49
50 pub fn into_inner(self) -> Decimal {
52 self.0
53 }
54}
55
56impl fmt::Display for UnsignedDecimal {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 write!(f, "{}", self.0)
59 }
60}
61
62impl FromStr for UnsignedDecimal {
63 type Err = O2Error;
64
65 fn from_str(s: &str) -> Result<Self, Self::Err> {
66 let d = Decimal::from_str(s)
67 .map_err(|e| O2Error::Other(format!("Invalid decimal '{s}': {e}")))?;
68 Self::new(d)
69 }
70}
71
72impl Serialize for UnsignedDecimal {
73 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
74 serializer.serialize_str(&self.0.to_string())
75 }
76}
77
78impl<'de> Deserialize<'de> for UnsignedDecimal {
79 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
80 let s = String::deserialize(deserializer)?;
81 let d = Decimal::from_str(&s).map_err(serde::de::Error::custom)?;
82 Self::new(d).map_err(serde::de::Error::custom)
83 }
84}
85
86impl From<u64> for UnsignedDecimal {
87 fn from(v: u64) -> Self {
88 Self(Decimal::from(v))
89 }
90}
91
92impl From<u32> for UnsignedDecimal {
93 fn from(v: u32) -> Self {
94 Self(Decimal::from(v))
95 }
96}
97
98impl Add for UnsignedDecimal {
99 type Output = Self;
100 fn add(self, rhs: Self) -> Self::Output {
101 Self(self.0 + rhs.0)
102 }
103}
104
105impl Mul for UnsignedDecimal {
106 type Output = Self;
107 fn mul(self, rhs: Self) -> Self::Output {
108 Self(self.0 * rhs.0)
109 }
110}
111
112impl Div for UnsignedDecimal {
113 type Output = Self;
114 fn div(self, rhs: Self) -> Self::Output {
115 Self(self.0 / rhs.0)
116 }
117}