1use rust_decimal::{
2 prelude::{FromPrimitive, ToPrimitive},
3 serde::float::{deserialize, serialize},
4 Decimal,
5};
6use serde::{
7 de::{Unexpected, Visitor},
8 forward_to_deserialize_any, Deserialize, Deserializer, Serialize,
9};
10use std::ops::{Add, Deref, Div, Mul, Neg, Rem, Sub};
11use std::{
12 fmt::{Debug, Display},
13 hash::{Hash, Hasher},
14};
15
16use crate::SerdeValueError;
17
18#[derive(Clone, Copy)]
19pub struct Number(Decimal);
20
21impl Debug for Number {
22 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 Debug::fmt(&self.0, formatter)
24 }
25}
26
27impl Display for Number {
28 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 Display::fmt(&self.0, formatter)
30 }
31}
32
33impl From<Decimal> for Number {
34 fn from(value: Decimal) -> Self {
35 Self(value)
36 }
37}
38
39impl Deref for Number {
40 type Target = Decimal;
41
42 fn deref(&self) -> &Self::Target {
43 &self.0
44 }
45}
46
47impl Serialize for Number {
48 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
49 where
50 S: serde::Serializer,
51 {
52 serialize(&self.0, serializer)
53 }
54}
55
56impl<'de> Deserialize<'de> for Number {
57 #[inline]
58 fn deserialize<D>(deserializer: D) -> Result<Number, D::Error>
59 where
60 D: Deserializer<'de>,
61 {
62 deserialize(deserializer).map(Number)
63 }
64}
65
66impl<'de> Deserializer<'de> for Number {
67 type Error = SerdeValueError;
68
69 #[inline]
70 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
71 where
72 V: Visitor<'de>,
73 {
74 let Some(f) = self.0.to_f64() else {
75 return Err(SerdeValueError::NumberOutOfRange);
76 };
77 visitor.visit_f64(f)
78 }
79
80 forward_to_deserialize_any! {
81 bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
82 bytes byte_buf option unit unit_struct newtype_struct seq tuple
83 tuple_struct map struct enum identifier ignored_any
84 }
85}
86
87impl<'de, 'a> Deserializer<'de> for &'a Number {
88 type Error = SerdeValueError;
89
90 #[inline]
91 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
92 where
93 V: Visitor<'de>,
94 {
95 let Some(f) = self.0.to_f64() else {
96 return Err(SerdeValueError::NumberOutOfRange);
97 };
98 visitor.visit_f64(f)
99 }
100
101 forward_to_deserialize_any! {
102 bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
103 bytes byte_buf option unit unit_struct newtype_struct seq tuple
104 tuple_struct map struct enum identifier ignored_any
105 }
106}
107
108macro_rules! from_integer {
109 ($($ty:ident)*) => {
110 $(
111 impl From<$ty> for Number {
112 #[inline]
113 #[allow(clippy::cast_sign_loss)]
114 fn from(n: $ty) -> Self {
115 Number(n.into())
116 }
117 }
118 )*
119 };
120}
121
122macro_rules! from_float {
123 ($($ty:ident)*) => {
124 $(
125 impl From<$ty> for Number {
126 #[inline]
127 #[allow(clippy::cast_sign_loss)]
128 fn from(n: $ty) -> Self {
129 Number(Decimal::from_f64(n as f64).unwrap())
131 }
132 }
133 )*
134 };
135}
136
137from_integer!(i8 i16 i32 i64 isize);
138from_integer!(u8 u16 u32 u64 usize);
139from_float!(f32 f64);
140
141pub(crate) fn unexpected(_number: &Number) -> Unexpected {
142 Unexpected::Other("number")
143}
144
145impl PartialEq for Number {
146 fn eq(&self, other: &Self) -> bool {
147 self.0.eq(&other.0)
148 }
149}
150
151impl Eq for Number {
152 fn assert_receiver_is_total_eq(&self) {
153 self.0.assert_receiver_is_total_eq()
154 }
155}
156
157impl PartialOrd for Number {
158 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
159 self.0.partial_cmp(&other.0)
160 }
161}
162
163impl Ord for Number {
164 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
165 self.0.cmp(&other.0)
166 }
167}
168
169impl Hash for Number {
170 fn hash<H: Hasher>(&self, state: &mut H) {
171 Decimal::hash(&self.0, state)
172 }
173}
174
175impl Neg for Number {
176 type Output = Number;
177
178 fn neg(self) -> Self::Output {
179 self.0.neg().into()
180 }
181}
182
183impl Add for Number {
184 type Output = Number;
185
186 fn add(self, rhs: Self) -> Self::Output {
187 self.0.add(rhs.0).into()
188 }
189}
190
191impl Sub for Number {
192 type Output = Number;
193
194 fn sub(self, rhs: Self) -> Self::Output {
195 self.0.sub(rhs.0).into()
196 }
197}
198
199impl Mul for Number {
200 type Output = Number;
201
202 fn mul(self, rhs: Self) -> Self::Output {
203 self.0.mul(rhs.0).into()
204 }
205}
206
207impl Div for Number {
208 type Output = Number;
209
210 fn div(self, rhs: Self) -> Self::Output {
211 self.0.div(rhs.0).into()
212 }
213}
214
215impl Rem for Number {
216 type Output = Number;
217
218 fn rem(self, rhs: Self) -> Self::Output {
219 self.0.rem(rhs.0).into()
220 }
221}