1use core::fmt;
2use std::fmt::Display;
3
4use rust_decimal::{
5 prelude::{FromPrimitive, ToPrimitive},
6 Decimal,
7};
8use serde::{de::Visitor, Deserialize, Serialize, Serializer};
9use std::hash::Hash;
10
11#[derive(Debug, PartialEq, Clone)]
12pub enum NumericLiteral {
13 Integer(isize),
14 Decimal(Decimal),
15 Double(f64),
16}
17
18impl NumericLiteral {
19 pub fn decimal(d: Decimal) -> NumericLiteral {
21 NumericLiteral::Decimal(d)
22 }
23
24 pub fn decimal_from_parts(whole: i64, fraction: u32) -> NumericLiteral {
25 let s = format!("{whole}.{fraction}");
26 let d = Decimal::from_str_exact(s.as_str()).unwrap();
27 NumericLiteral::Decimal(d)
28 }
29
30 pub fn decimal_from_f64(d: f64) -> NumericLiteral {
31 let d: Decimal = Decimal::from_f64(d).unwrap();
32 NumericLiteral::Decimal(d)
33 }
34
35 pub fn decimal_from_isize(d: isize) -> NumericLiteral {
36 let d: Decimal = Decimal::from_isize(d).unwrap();
37 NumericLiteral::Decimal(d)
38 }
39
40 pub fn decimal_from_i32(d: i32) -> NumericLiteral {
41 let d: Decimal = Decimal::from_i32(d).unwrap();
42 NumericLiteral::Decimal(d)
43 }
44
45 pub fn decimal_from_i64(d: i64) -> NumericLiteral {
46 let d: Decimal = Decimal::from_i64(d).unwrap();
47 NumericLiteral::Decimal(d)
48 }
49
50 pub fn decimal_from_u128(d: u128) -> NumericLiteral {
51 let d: Decimal = Decimal::from_u128(d).unwrap();
52 NumericLiteral::Decimal(d)
53 }
54
55 pub fn decimal_from_i128(d: i128) -> NumericLiteral {
56 let d: Decimal = Decimal::from_i128(d).unwrap();
57 NumericLiteral::Decimal(d)
58 }
59
60 pub fn integer_from_i128(d: i128) -> NumericLiteral {
61 let d: Decimal = Decimal::from_i128(d).unwrap();
62 let n: isize = Decimal::to_isize(&d).unwrap();
63 NumericLiteral::Integer(n)
64 }
65
66 pub fn decimal_from_u64(d: u64) -> NumericLiteral {
67 let d: Decimal = Decimal::from_u64(d).unwrap();
68 NumericLiteral::Decimal(d)
69 }
70
71 pub fn decimal_from_u32(d: u32) -> NumericLiteral {
72 let d: Decimal = Decimal::from_u32(d).unwrap();
73 NumericLiteral::Decimal(d)
74 }
75
76 pub fn decimal_from_f32(d: f32) -> NumericLiteral {
77 let d: Decimal = Decimal::from_f32(d).unwrap();
78 NumericLiteral::Decimal(d)
79 }
80
81 pub fn integer(n: isize) -> NumericLiteral {
82 NumericLiteral::Integer(n)
83 }
84
85 pub fn double(d: f64) -> NumericLiteral {
86 NumericLiteral::Double(d)
87 }
88
89 pub fn lexical_form(&self) -> String {
90 self.to_string()
91 }
92
93 pub fn as_decimal(&self) -> Decimal {
94 match self {
95 NumericLiteral::Integer(n) => Decimal::from_isize(*n).unwrap(),
96 NumericLiteral::Double(d) => Decimal::from_f64(*d).unwrap(),
97 NumericLiteral::Decimal(d) => *d,
98 }
99 }
100
101 pub fn less_than(&self, other: &NumericLiteral) -> bool {
102 match (self, other) {
103 (NumericLiteral::Integer(n1), NumericLiteral::Integer(n2)) => n1 < n2,
104 (v1, v2) => v1.as_decimal() < v2.as_decimal(),
105 }
106 }
107}
108
109impl Eq for NumericLiteral {}
110
111impl Hash for NumericLiteral {
112 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
113 core::mem::discriminant(self).hash(state);
114 }
116}
117
118impl Serialize for NumericLiteral {
119 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
120 where
121 S: Serializer,
122 {
123 match self {
124 NumericLiteral::Integer(n) => {
125 let c: u128 = (*n) as u128;
126 serializer.serialize_u128(c)
127 }
128 NumericLiteral::Decimal(d) => {
129 let f: f64 = (*d).try_into().unwrap();
130 serializer.serialize_f64(f)
131 }
132 NumericLiteral::Double(d) => serializer.serialize_f64(*d),
133 }
134 }
135}
136
137impl<'de> Deserialize<'de> for NumericLiteral {
138 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
139 where
140 D: serde::Deserializer<'de>,
141 {
142 struct NumericLiteralVisitor;
143
144 impl Visitor<'_> for NumericLiteralVisitor {
145 type Value = NumericLiteral;
146
147 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
148 formatter.write_str("NumericLiteral")
149 }
150
151 fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
152 where
153 E: serde::de::Error,
154 {
155 Ok(NumericLiteral::decimal_from_i32(v))
156 }
157
158 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
159 where
160 E: serde::de::Error,
161 {
162 Ok(NumericLiteral::decimal_from_i64(v))
163 }
164
165 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
166 where
167 E: serde::de::Error,
168 {
169 Ok(NumericLiteral::decimal_from_u64(v))
170 }
171
172 fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
173 where
174 E: serde::de::Error,
175 {
176 Ok(NumericLiteral::decimal_from_u32(v))
177 }
178
179 fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
180 where
181 E: serde::de::Error,
182 {
183 Ok(NumericLiteral::decimal_from_u128(v))
184 }
185
186 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
187 where
188 E: serde::de::Error,
189 {
190 Ok(NumericLiteral::decimal_from_f64(v))
191 }
192
193 fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
194 where
195 E: serde::de::Error,
196 {
197 Ok(NumericLiteral::decimal_from_f32(v))
198 }
199 }
200
201 deserializer.deserialize_any(NumericLiteralVisitor)
202 }
203}
204
205impl Display for NumericLiteral {
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217 match self {
218 NumericLiteral::Double(d) => write!(f, "{}", d),
219 NumericLiteral::Integer(n) => write!(f, "{}", n),
220 NumericLiteral::Decimal(d) => write!(f, "{}", d),
221 }
222 }
223}
224
225#[cfg(test)]
226mod tests {
227 use super::*;
228 use rust_decimal_macros::dec;
229
230 #[test]
231 fn test_serialize_integer() {
232 let n = NumericLiteral::Integer(23);
233 let json_nc = serde_json::to_string(&n).unwrap();
234 assert_eq!(json_nc, "23");
235 }
236
237 #[test]
238 fn test_deserialize_integer() {
239 let str = r#"23"#;
240 let deser: NumericLiteral = serde_json::from_str(str).unwrap();
241 let expected = NumericLiteral::decimal(dec![23]);
242 assert_eq!(deser, expected);
243 }
244
245 #[test]
246 fn test_serialize_decimal() {
247 let n = NumericLiteral::Decimal(dec!(5.35));
248 let expected = r#"5.35"#;
249 let json = serde_json::to_string(&n).unwrap();
250 assert_eq!(json, expected);
251 }
252
253 #[test]
254 fn test_deserialize_decimal() {
255 let str = r#"5.35"#;
256 let deser: NumericLiteral = serde_json::from_str(str).unwrap();
257 let expected = NumericLiteral::Decimal(dec!(5.35));
258 assert_eq!(deser, expected);
259 }
260}