1use std::cmp::Ordering;
2use std::fmt::{self, Display};
3use std::hash;
4
5use rust_decimal::Decimal;
6use rust_decimal::prelude::ToPrimitive;
7use serde::{Deserialize, Serialize};
8
9use crate::Kind;
10use crate::sql::{SqlFormat, ToSql};
11
12#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
18#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
19pub enum Number {
20 Int(i64),
22 Float(f64),
24 Decimal(Decimal),
26}
27
28impl Number {
29 pub const NAN: Self = Self::Float(f64::NAN);
31
32 pub fn is_nan(&self) -> bool {
34 matches!(self, Number::Float(v) if v.is_nan())
35 }
36
37 pub fn to_int(&self) -> Option<i64> {
41 match self {
42 Number::Int(v) => Some(*v),
43 Number::Float(v) => Some(*v as i64),
44 Number::Decimal(v) => v.to_i64(),
45 }
46 }
47
48 pub fn to_f64(&self) -> Option<f64> {
52 match self {
53 Number::Int(v) => Some(*v as f64),
54 Number::Float(v) => Some(*v),
55 Number::Decimal(v) => v.to_f64(),
56 }
57 }
58}
59
60impl Display for Number {
61 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62 match self {
63 Number::Int(v) => Display::fmt(v, f),
64 Number::Float(v) => {
65 if v.is_finite() {
66 write!(f, "{v}f")
68 } else {
69 Display::fmt(v, f)
71 }
72 }
73 Number::Decimal(v) => write!(f, "{v}dec"),
74 }
75 }
76}
77
78impl ToSql for Number {
79 fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
80 match self {
81 Number::Int(v) => f.push_str(&v.to_string()),
82 Number::Float(v) => {
83 if v.is_finite() {
84 f.push_str(&v.to_string());
85 f.push('f');
86 } else {
87 f.push_str(&v.to_string());
89 }
90 }
91 Number::Decimal(v) => v.fmt_sql(f, fmt),
92 }
93 }
94}
95
96macro_rules! impl_number {
97 ($($variant:ident($type:ty) => ($is:ident, $into:ident, $from:ident),)+) => {
98 impl Number {
99 pub fn kind(&self) -> Kind {
101 match self {
102 $(
103 Self::$variant(_) => Kind::$variant,
104 )+
105 }
106 }
107
108 $(
109 pub fn $is(&self) -> bool {
111 matches!(self, Self::$variant(_))
112 }
113
114 pub fn $into(self) -> anyhow::Result<$type> {
116 if let Self::$variant(v) = self {
117 Ok(v)
118 } else {
119 Err(anyhow::anyhow!("Expected a {} but got a {}", Kind::$variant, self.kind()))
120 }
121 }
122
123 pub fn $from(v: $type) -> Self {
125 Self::$variant(v)
126 }
127 )+
128 }
129 }
130}
131
132impl_number! (
133 Int(i64) => (is_int, into_int, from_int),
134 Float(f64) => (is_float, into_float, from_float),
135 Decimal(Decimal) => (is_decimal, into_decimal, from_decimal),
136);
137
138impl Default for Number {
139 fn default() -> Self {
140 Self::Int(0)
141 }
142}
143
144impl Eq for Number {}
145
146impl Ord for Number {
147 fn cmp(&self, other: &Self) -> Ordering {
148 fn total_cmp_f64(a: f64, b: f64) -> Ordering {
149 if a == 0.0 && b == 0.0 {
150 Ordering::Equal
152 } else {
153 a.total_cmp(&b)
155 }
156 }
157
158 macro_rules! greater {
160 ($f:ident) => {
161 if $f.is_sign_positive() {
162 Ordering::Greater
163 } else {
164 Ordering::Less
165 }
166 };
167 }
168
169 match (self, other) {
170 (Number::Int(v), Number::Int(w)) => v.cmp(w),
171 (Number::Float(v), Number::Float(w)) => total_cmp_f64(*v, *w),
172 (Number::Decimal(v), Number::Decimal(w)) => v.cmp(w),
173 (Number::Int(v), Number::Float(w)) => {
175 if !w.is_finite() {
177 return greater!(w).reverse();
178 }
179 let l = *v as i128;
181 let r = *w as i128;
183 match l.cmp(&r) {
185 Ordering::Equal => total_cmp_f64(0.0, w.fract()),
187 ordering => ordering,
189 }
190 }
191 (v @ Number::Float(_), w @ Number::Int(_)) => w.cmp(v).reverse(),
192 (Number::Int(v), Number::Decimal(w)) => Decimal::from(*v).cmp(w),
194 (Number::Decimal(v), Number::Int(w)) => v.cmp(&Decimal::from(*w)),
195 (Number::Float(v), Number::Decimal(w)) => {
197 macro_rules! compare_fractions {
199 ($l:ident, $r:ident) => {
200 match ($l == 0.0, $r == Decimal::ZERO) {
201 (true, true) => {
203 return Ordering::Equal;
204 }
205 (true, false) => {
207 return greater!($r).reverse();
208 }
209 (false, true) => {
211 return greater!($l);
212 }
213 (false, false) => {
215 continue;
216 }
217 }
218 };
219 }
220 if !v.is_finite() {
222 return greater!(v);
223 }
224 let l = *v as i128;
226 let Ok(r) = i128::try_from(*w) else {
228 return greater!(w).reverse();
229 };
230 match l.cmp(&r) {
232 Ordering::Equal => {
234 const SAFE_MULTIPLIER: i64 = 9_007_199_254_740_000;
249 let mut l = v.fract();
251 let mut r = w.fract();
253 for _ in 0..12 {
258 l *= SAFE_MULTIPLIER as f64;
259 r *= Decimal::new(SAFE_MULTIPLIER, 0);
260 match r.to_i64() {
263 Some(ref right) => match (l as i64).cmp(right) {
264 Ordering::Equal => {
267 l = l.fract();
269 r = r.fract();
270 compare_fractions!(l, r);
273 }
274 ordering => {
275 return ordering;
278 }
279 },
280 None => {
284 return greater!(w).reverse();
287 }
288 }
289 }
290 Ordering::Equal
295 }
296 ordering => ordering,
298 }
299 }
300 (v @ Number::Decimal(..), w @ Number::Float(..)) => w.cmp(v).reverse(),
301 }
302 }
303}
304
305impl hash::Hash for Number {
308 fn hash<H: hash::Hasher>(&self, state: &mut H) {
309 match self {
310 Number::Int(v) => v.hash(state),
311 Number::Float(v) => v.to_bits().hash(state),
312 Number::Decimal(v) => v.hash(state),
313 }
314 }
315}
316
317impl PartialEq for Number {
318 fn eq(&self, other: &Self) -> bool {
319 fn total_eq_f64(a: f64, b: f64) -> bool {
320 a.to_bits().eq(&b.to_bits()) || (a == 0.0 && b == 0.0)
321 }
322
323 match (self, other) {
324 (Number::Int(v), Number::Int(w)) => v.eq(w),
325 (Number::Float(v), Number::Float(w)) => total_eq_f64(*v, *w),
326 (Number::Decimal(v), Number::Decimal(w)) => v.eq(w),
327 (v @ Number::Int(_), w @ Number::Float(_)) => v.cmp(w) == Ordering::Equal,
329 (v @ Number::Float(_), w @ Number::Int(_)) => v.cmp(w) == Ordering::Equal,
330 (Number::Int(v), Number::Decimal(w)) => Decimal::from(*v).eq(w),
332 (Number::Decimal(v), Number::Int(w)) => v.eq(&Decimal::from(*w)),
333 (v @ Number::Float(_), w @ Number::Decimal(_)) => v.cmp(w) == Ordering::Equal,
335 (v @ Number::Decimal(_), w @ Number::Float(_)) => v.cmp(w) == Ordering::Equal,
336 }
337 }
338}
339
340impl PartialOrd for Number {
341 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
342 Some(self.cmp(other))
343 }
344}
345
346impl From<i32> for Number {
348 fn from(value: i32) -> Self {
349 Number::Int(value as i64)
350 }
351}
352
353impl From<i64> for Number {
354 fn from(value: i64) -> Self {
355 Number::Int(value)
356 }
357}
358
359impl From<f32> for Number {
360 fn from(value: f32) -> Self {
361 Number::Float(value as f64)
362 }
363}
364
365impl From<f64> for Number {
366 fn from(value: f64) -> Self {
367 Number::Float(value)
368 }
369}
370
371impl From<Decimal> for Number {
372 fn from(value: Decimal) -> Self {
373 Number::Decimal(value)
374 }
375}