reifydb_type/value/decimal/
mod.rs1use std::{
5 cmp::Ordering,
6 fmt::{Display, Formatter},
7 ops::Deref,
8 str::FromStr,
9};
10
11use bigdecimal::{BigDecimal as BigDecimalInner, FromPrimitive};
12use num_traits::{One, Zero};
13use serde::{
14 Deserialize, Deserializer, Serialize, Serializer,
15 de::{self, Visitor},
16};
17
18use super::{int::Int, uint::Uint};
19use crate::{Error, OwnedFragment, Type, error};
20
21mod parse;
22
23pub use parse::parse_decimal;
24
25use crate::error::diagnostic::number::invalid_number_format;
26
27#[repr(transparent)]
28#[derive(Clone, Debug)]
29pub struct Decimal(pub BigDecimalInner);
30
31impl Decimal {
32 pub fn zero() -> Self {
33 Self(BigDecimalInner::zero())
34 }
35
36 pub fn one() -> Self {
37 Self(BigDecimalInner::one())
38 }
39}
40
41impl Deref for Decimal {
42 type Target = BigDecimalInner;
43
44 fn deref(&self) -> &Self::Target {
45 &self.0
46 }
47}
48
49impl Decimal {
50 pub fn new(value: BigDecimalInner) -> Self {
51 Self(value)
52 }
53
54 pub fn from_bigdecimal(value: BigDecimalInner) -> Self {
55 Self(value)
56 }
57
58 pub fn with_scale(value: BigDecimalInner, scale: i64) -> Self {
59 Self(value.with_scale(scale))
60 }
61
62 pub fn from_i64(value: i64) -> Self {
63 Self(BigDecimalInner::from(value))
64 }
65
66 pub fn inner(&self) -> &BigDecimalInner {
67 &self.0
68 }
69
70 pub fn to_bigdecimal(self) -> BigDecimalInner {
71 self.0
72 }
73
74 pub fn negate(self) -> Self {
75 Self(-self.0)
76 }
77}
78
79impl PartialEq for Decimal {
80 fn eq(&self, other: &Self) -> bool {
81 self.0 == other.0
82 }
83}
84
85impl Eq for Decimal {}
86
87impl PartialOrd for Decimal {
88 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
89 Some(self.cmp(other))
90 }
91}
92
93impl Ord for Decimal {
94 fn cmp(&self, other: &Self) -> Ordering {
95 self.0.cmp(&other.0)
96 }
97}
98
99impl Display for Decimal {
100 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
101 self.0.fmt(f)
102 }
103}
104
105impl std::hash::Hash for Decimal {
106 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
107 self.0.to_string().hash(state);
108 }
109}
110
111impl FromStr for Decimal {
112 type Err = Error;
113
114 fn from_str(s: &str) -> Result<Self, Self::Err> {
115 let big_decimal = BigDecimalInner::from_str(s)
116 .map_err(|_| error!(invalid_number_format(OwnedFragment::None, Type::Decimal)))?;
117
118 Ok(Self(big_decimal))
119 }
120}
121
122impl From<i64> for Decimal {
123 fn from(value: i64) -> Self {
124 Self(BigDecimalInner::from(value))
125 }
126}
127
128impl From<i8> for Decimal {
129 fn from(value: i8) -> Self {
130 Self::from(value as i64)
131 }
132}
133
134impl From<i16> for Decimal {
135 fn from(value: i16) -> Self {
136 Self::from(value as i64)
137 }
138}
139
140impl From<i32> for Decimal {
141 fn from(value: i32) -> Self {
142 Self::from(value as i64)
143 }
144}
145
146impl From<i128> for Decimal {
147 fn from(value: i128) -> Self {
148 Self(BigDecimalInner::from(value))
149 }
150}
151
152impl From<u8> for Decimal {
153 fn from(value: u8) -> Self {
154 Self::from(value as i64)
155 }
156}
157
158impl From<u16> for Decimal {
159 fn from(value: u16) -> Self {
160 Self::from(value as i64)
161 }
162}
163
164impl From<u32> for Decimal {
165 fn from(value: u32) -> Self {
166 Self::from(value as i64)
167 }
168}
169
170impl From<u64> for Decimal {
171 fn from(value: u64) -> Self {
172 Self(BigDecimalInner::from(value))
173 }
174}
175
176impl From<u128> for Decimal {
177 fn from(value: u128) -> Self {
178 Self(BigDecimalInner::from(value))
179 }
180}
181
182impl From<f32> for Decimal {
183 fn from(value: f32) -> Self {
184 let inner = BigDecimalInner::from_f32(value).unwrap_or_else(|| BigDecimalInner::from(0));
185 Self(inner)
186 }
187}
188
189impl From<f64> for Decimal {
190 fn from(value: f64) -> Self {
191 let inner = BigDecimalInner::from_f64(value).unwrap_or_else(|| BigDecimalInner::from(0));
192 Self(inner)
193 }
194}
195
196impl From<BigDecimalInner> for Decimal {
197 fn from(value: BigDecimalInner) -> Self {
198 Self(value)
199 }
200}
201
202impl From<Int> for Decimal {
203 fn from(value: Int) -> Self {
204 Self(BigDecimalInner::from_bigint(value.0, 0))
205 }
206}
207
208impl From<Uint> for Decimal {
209 fn from(value: Uint) -> Self {
210 Self(BigDecimalInner::from_bigint(value.0, 0))
211 }
212}
213
214impl Default for Decimal {
215 fn default() -> Self {
216 Self::zero()
217 }
218}
219
220impl Serialize for Decimal {
223 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
224 where
225 S: Serializer,
226 {
227 serializer.serialize_str(&self.0.to_string())
228 }
229}
230
231struct DecimalVisitor;
232
233impl<'de> Visitor<'de> for DecimalVisitor {
234 type Value = Decimal;
235
236 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
237 formatter.write_str("a decimal number as a string")
238 }
239
240 fn visit_str<E>(self, value: &str) -> Result<Decimal, E>
241 where
242 E: de::Error,
243 {
244 BigDecimalInner::from_str(value).map(Decimal).map_err(|e| E::custom(format!("invalid decimal: {}", e)))
245 }
246}
247
248impl<'de> Deserialize<'de> for Decimal {
249 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
250 where
251 D: Deserializer<'de>,
252 {
253 deserializer.deserialize_str(DecimalVisitor)
254 }
255}
256
257#[cfg(test)]
258mod tests {
259 use bincode::{
260 config::standard,
261 serde::{decode_from_slice, encode_to_vec},
262 };
263
264 use super::*;
265
266 #[test]
267 fn test_new_decimal_valid() {
268 let bd = BigDecimalInner::from_str("123.45").unwrap();
269 let decimal = Decimal::new(bd);
270 assert_eq!(decimal.to_string(), "123.45");
271 }
272
273 #[test]
274 fn test_from_str() {
275 let decimal = Decimal::from_str("123.45").unwrap();
276 assert_eq!(decimal.to_string(), "123.45");
277 }
278
279 #[test]
280 fn test_comparison() {
281 let d1 = Decimal::from_str("123.45").unwrap();
282 let d2 = Decimal::from_str("123.46").unwrap();
283 let d3 = Decimal::from_str("123.45").unwrap();
284
285 assert!(d1 < d2);
286 assert_eq!(d1, d3);
287 }
288
289 #[test]
290 fn test_display() {
291 let decimal = Decimal::from_str("123.45").unwrap();
292 assert_eq!(format!("{}", decimal), "123.45");
293 }
294
295 #[test]
296 fn test_serde_json() {
297 let decimal = Decimal::from_str("123.456789").unwrap();
298 let json = serde_json::to_string(&decimal).unwrap();
299 assert_eq!(json, "\"123.456789\"");
300
301 let deserialized: Decimal = serde_json::from_str(&json).unwrap();
302 assert_eq!(deserialized, decimal);
303 }
304
305 #[test]
306 fn test_serde_json_negative() {
307 let decimal = Decimal::from_str("-987.654321").unwrap();
308 let json = serde_json::to_string(&decimal).unwrap();
309 assert_eq!(json, "\"-987.654321\"");
310
311 let deserialized: Decimal = serde_json::from_str(&json).unwrap();
312 assert_eq!(deserialized, decimal);
313 }
314
315 #[test]
316 fn test_serde_json_zero() {
317 let decimal = Decimal::zero();
318 let json = serde_json::to_string(&decimal).unwrap();
319 assert_eq!(json, "\"0\"");
320
321 let deserialized: Decimal = serde_json::from_str(&json).unwrap();
322 assert_eq!(deserialized, decimal);
323 }
324
325 #[test]
326 fn test_serde_json_high_precision() {
327 let decimal = Decimal::from_str("123456789.123456789123456789").unwrap();
328 let json = serde_json::to_string(&decimal).unwrap();
329
330 let deserialized: Decimal = serde_json::from_str(&json).unwrap();
331 assert_eq!(deserialized, decimal);
332 }
333
334 #[test]
335 fn test_serde_bincode() {
336 let decimal = Decimal::from_str("123.456789").unwrap();
337 let encoded = encode_to_vec(&decimal, standard()).unwrap();
338
339 let (decoded, _): (Decimal, usize) = decode_from_slice(&encoded, standard()).unwrap();
340 assert_eq!(decoded, decimal);
341 }
342
343 #[test]
344 fn test_serde_bincode_negative() {
345 let decimal = Decimal::from_str("-987.654321").unwrap();
346 let encoded = encode_to_vec(&decimal, standard()).unwrap();
347
348 let (decoded, _): (Decimal, usize) = decode_from_slice(&encoded, standard()).unwrap();
349 assert_eq!(decoded, decimal);
350 }
351
352 #[test]
353 fn test_serde_bincode_zero() {
354 let decimal = Decimal::zero();
355 let encoded = encode_to_vec(&decimal, standard()).unwrap();
356
357 let (decoded, _): (Decimal, usize) = decode_from_slice(&encoded, standard()).unwrap();
358 assert_eq!(decoded, decimal);
359 }
360
361 #[test]
362 fn test_serde_bincode_high_precision() {
363 let decimal = Decimal::from_str("123456789.123456789123456789").unwrap();
364 let encoded = encode_to_vec(&decimal, standard()).unwrap();
365
366 let (decoded, _): (Decimal, usize) = decode_from_slice(&encoded, standard()).unwrap();
367 assert_eq!(decoded, decimal);
368 }
369
370 #[test]
371 fn test_serde_bincode_large_number() {
372 let decimal = Decimal::from_str("999999999999999999999999999999.999999999999999999999999").unwrap();
373 let encoded = encode_to_vec(&decimal, standard()).unwrap();
374
375 let (decoded, _): (Decimal, usize) = decode_from_slice(&encoded, standard()).unwrap();
376 assert_eq!(decoded, decimal);
377 }
378}