srdf/
numeric_literal.rs

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    /// Creates a numeric literal from a decimal
20    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        // self.to_string().hash(state)
115    }
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
205/*impl ToString for NumericLiteral {
206    fn to_string(&self) -> String {
207        match self {
208            NumericLiteral::Double(d) => format!("{}", d),
209            NumericLiteral::Integer(n) => n.to_string(),
210            NumericLiteral::Decimal(d) => d.to_string(),
211        }
212    }
213}*/
214
215impl 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}