1use super::value::{TryAdd, TryDiv, TryMul, TryNeg, TryPow, TrySub};
2use crate::err::Error;
3use crate::strand::Strand;
4use revision::revisioned;
5use rust_decimal::prelude::*;
6use serde::{Deserialize, Serialize};
7use std::cmp::Ordering;
8use std::fmt::{self, Display, Formatter};
9use std::hash;
10use std::iter::Product;
11use std::iter::Sum;
12use std::ops::{self, Add, Div, Mul, Neg, Sub};
13use std::str::FromStr;
14
15pub(crate) const TOKEN: &str = "$surrealdb::private::crate::Number";
16
17#[derive(Clone, Debug, Serialize, Deserialize)]
18#[serde(rename = "$surrealdb::private::crate::Number")]
19#[revisioned(revision = 1)]
20pub enum Number {
21 Int(i64),
22 Float(f64),
23 Decimal(Decimal),
24 }
26
27impl Default for Number {
28 fn default() -> Self {
29 Self::Int(0)
30 }
31}
32
33macro_rules! from_prim_ints {
34 ($($int: ty),*) => {
35 $(
36 impl From<$int> for Number {
37 fn from(i: $int) -> Self {
38 Self::Int(i as i64)
39 }
40 }
41 )*
42 };
43}
44
45from_prim_ints!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize);
46
47impl From<f32> for Number {
48 fn from(f: f32) -> Self {
49 Self::Float(f as f64)
50 }
51}
52
53impl From<f64> for Number {
54 fn from(f: f64) -> Self {
55 Self::Float(f)
56 }
57}
58
59impl From<Decimal> for Number {
60 fn from(v: Decimal) -> Self {
61 Self::Decimal(v)
62 }
63}
64
65impl FromStr for Number {
66 type Err = ();
67 fn from_str(s: &str) -> Result<Self, Self::Err> {
68 Self::try_from(s)
69 }
70}
71
72impl TryFrom<String> for Number {
73 type Error = ();
74 fn try_from(v: String) -> Result<Self, Self::Error> {
75 Self::try_from(v.as_str())
76 }
77}
78
79impl TryFrom<Strand> for Number {
80 type Error = ();
81 fn try_from(v: Strand) -> Result<Self, Self::Error> {
82 Self::try_from(v.as_str())
83 }
84}
85
86impl TryFrom<&str> for Number {
87 type Error = ();
88 fn try_from(v: &str) -> Result<Self, Self::Error> {
89 match v.parse::<i64>() {
91 Ok(v) => Ok(Self::Int(v)),
93 _ => match f64::from_str(v) {
95 Ok(v) => Ok(Self::Float(v)),
97 _ => Err(()),
99 },
100 }
101 }
102}
103
104macro_rules! try_into_prim {
105 ($($int: ty => $to_int: ident),*) => {
107 $(
108 impl TryFrom<Number> for $int {
109 type Error = Error;
110 fn try_from(value: Number) -> Result<Self, Self::Error> {
111 match value {
112 Number::Int(v) => match v.$to_int() {
113 Some(v) => Ok(v),
114 None => Err(Error::TryFrom(value.to_string(), stringify!($int))),
115 },
116 Number::Float(v) => match v.$to_int() {
117 Some(v) => Ok(v),
118 None => Err(Error::TryFrom(value.to_string(), stringify!($int))),
119 },
120 Number::Decimal(ref v) => match v.$to_int() {
121 Some(v) => Ok(v),
122 None => Err(Error::TryFrom(value.to_string(), stringify!($int))),
123 },
124 }
125 }
126 }
127 )*
128 };
129}
130
131try_into_prim!(
132 i8 => to_i8, i16 => to_i16, i32 => to_i32, i64 => to_i64, i128 => to_i128,
133 u8 => to_u8, u16 => to_u16, u32 => to_u32, u64 => to_u64, u128 => to_u128,
134 f32 => to_f32, f64 => to_f64
135);
136
137impl TryFrom<Number> for Decimal {
138 type Error = Error;
139 fn try_from(value: Number) -> Result<Self, Self::Error> {
140 match value {
141 Number::Int(v) => match Decimal::from_i64(v) {
142 Some(v) => Ok(v),
143 None => Err(Error::TryFrom(value.to_string(), "Decimal")),
144 },
145 Number::Float(v) => match Decimal::try_from(v) {
146 Ok(v) => Ok(v),
147 _ => Err(Error::TryFrom(value.to_string(), "Decimal")),
148 },
149 Number::Decimal(x) => Ok(x),
150 }
151 }
152}
153
154impl Display for Number {
155 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
156 match self {
157 Number::Int(v) => Display::fmt(v, f),
158 Number::Float(v) => {
159 if v.is_finite() {
160 write!(f, "{v}f")
162 } else {
163 Display::fmt(v, f)
165 }
166 }
167 Number::Decimal(v) => write!(f, "{v}dec"),
168 }
169 }
170}
171
172impl Number {
173 pub const NAN: Number = Number::Float(f64::NAN);
178
179 pub fn is_nan(&self) -> bool {
184 matches!(self, Number::Float(v) if v.is_nan())
185 }
186
187 pub fn is_int(&self) -> bool {
188 matches!(self, Number::Int(_))
189 }
190
191 pub fn is_float(&self) -> bool {
192 matches!(self, Number::Float(_))
193 }
194
195 pub fn is_decimal(&self) -> bool {
196 matches!(self, Number::Decimal(_))
197 }
198
199 pub fn is_integer(&self) -> bool {
200 match self {
201 Number::Int(_) => true,
202 Number::Float(v) => v.fract() == 0.0,
203 Number::Decimal(v) => v.is_integer(),
204 }
205 }
206
207 pub fn is_truthy(&self) -> bool {
208 match self {
209 Number::Int(v) => v != &0,
210 Number::Float(v) => v != &0.0,
211 Number::Decimal(v) => v != &Decimal::ZERO,
212 }
213 }
214
215 pub fn is_positive(&self) -> bool {
216 match self {
217 Number::Int(v) => v > &0,
218 Number::Float(v) => v > &0.0,
219 Number::Decimal(v) => v > &Decimal::ZERO,
220 }
221 }
222
223 pub fn is_negative(&self) -> bool {
224 match self {
225 Number::Int(v) => v < &0,
226 Number::Float(v) => v < &0.0,
227 Number::Decimal(v) => v < &Decimal::ZERO,
228 }
229 }
230
231 pub fn is_zero(&self) -> bool {
232 match self {
233 Number::Int(v) => v == &0,
234 Number::Float(v) => v == &0.0,
235 Number::Decimal(v) => v == &Decimal::ZERO,
236 }
237 }
238
239 pub fn is_zero_or_positive(&self) -> bool {
240 match self {
241 Number::Int(v) => v >= &0,
242 Number::Float(v) => v >= &0.0,
243 Number::Decimal(v) => v >= &Decimal::ZERO,
244 }
245 }
246
247 pub fn is_zero_or_negative(&self) -> bool {
248 match self {
249 Number::Int(v) => v <= &0,
250 Number::Float(v) => v <= &0.0,
251 Number::Decimal(v) => v <= &Decimal::ZERO,
252 }
253 }
254
255 pub fn as_usize(self) -> usize {
260 match self {
261 Number::Int(v) => v as usize,
262 Number::Float(v) => v as usize,
263 Number::Decimal(v) => v.try_into().unwrap_or_default(),
264 }
265 }
266
267 pub fn as_int(self) -> i64 {
268 match self {
269 Number::Int(v) => v,
270 Number::Float(v) => v as i64,
271 Number::Decimal(v) => v.try_into().unwrap_or_default(),
272 }
273 }
274
275 pub fn as_float(self) -> f64 {
276 match self {
277 Number::Int(v) => v as f64,
278 Number::Float(v) => v,
279 Number::Decimal(v) => v.try_into().unwrap_or_default(),
280 }
281 }
282
283 pub fn as_decimal(self) -> Decimal {
284 match self {
285 Number::Int(v) => Decimal::from(v),
286 Number::Float(v) => Decimal::try_from(v).unwrap_or_default(),
287 Number::Decimal(v) => v,
288 }
289 }
290
291 pub fn to_usize(&self) -> usize {
296 match self {
297 Number::Int(v) => *v as usize,
298 Number::Float(v) => *v as usize,
299 Number::Decimal(v) => v.to_usize().unwrap_or_default(),
300 }
301 }
302
303 pub fn to_int(&self) -> i64 {
304 match self {
305 Number::Int(v) => *v,
306 Number::Float(v) => *v as i64,
307 Number::Decimal(v) => v.to_i64().unwrap_or_default(),
308 }
309 }
310
311 pub fn to_float(&self) -> f64 {
312 match self {
313 Number::Int(v) => *v as f64,
314 Number::Float(v) => *v,
315 &Number::Decimal(v) => v.try_into().unwrap_or_default(),
316 }
317 }
318
319 pub fn to_decimal(&self) -> Decimal {
320 match self {
321 #[allow(warnings)]
324 Number::Int(v) => Decimal::try_from(*v).unwrap_or_default(),
325 Number::Float(v) => Decimal::try_from(*v).unwrap_or_default(),
326 Number::Decimal(v) => *v,
327 }
328 }
329
330 pub fn abs(self) -> Self {
335 match self {
336 Number::Int(v) => v.abs().into(),
337 Number::Float(v) => v.abs().into(),
338 Number::Decimal(v) => v.abs().into(),
339 }
340 }
341
342 pub fn acos(self) -> Self {
343 self.to_float().acos().into()
344 }
345
346 pub fn ceil(self) -> Self {
347 match self {
348 Number::Int(v) => v.into(),
349 Number::Float(v) => v.ceil().into(),
350 Number::Decimal(v) => v.ceil().into(),
351 }
352 }
353
354 pub fn floor(self) -> Self {
355 match self {
356 Number::Int(v) => v.into(),
357 Number::Float(v) => v.floor().into(),
358 Number::Decimal(v) => v.floor().into(),
359 }
360 }
361
362 pub fn round(self) -> Self {
363 match self {
364 Number::Int(v) => v.into(),
365 Number::Float(v) => v.round().into(),
366 Number::Decimal(v) => v.round().into(),
367 }
368 }
369
370 pub fn fixed(self, precision: usize) -> Number {
371 match self {
372 Number::Int(v) => format!("{v:.precision$}").try_into().unwrap_or_default(),
373 Number::Float(v) => format!("{v:.precision$}").try_into().unwrap_or_default(),
374 Number::Decimal(v) => v.round_dp(precision as u32).into(),
375 }
376 }
377
378 pub fn sqrt(self) -> Self {
379 match self {
380 Number::Int(v) => (v as f64).sqrt().into(),
381 Number::Float(v) => v.sqrt().into(),
382 Number::Decimal(v) => v.sqrt().unwrap_or_default().into(),
383 }
384 }
385
386 pub fn pow(self, power: Number) -> Number {
387 match (self, power) {
388 (Number::Int(v), Number::Int(p)) => Number::Int(v.pow(p as u32)),
389 (Number::Decimal(v), Number::Int(p)) => v.powi(p).into(),
390 (v, p) => v.as_float().powf(p.as_float()).into(),
393 }
394 }
395}
396
397impl Eq for Number {}
398
399impl Ord for Number {
400 fn cmp(&self, other: &Self) -> Ordering {
401 fn total_cmp_f64(a: f64, b: f64) -> Ordering {
402 if a == 0.0 && b == 0.0 {
403 Ordering::Equal
405 } else {
406 a.total_cmp(&b)
408 }
409 }
410
411 match (self, other) {
412 (Number::Int(v), Number::Int(w)) => v.cmp(w),
413 (Number::Float(v), Number::Float(w)) => total_cmp_f64(*v, *w),
414 (Number::Decimal(v), Number::Decimal(w)) => v.cmp(w),
415 (Number::Int(v), Number::Float(w)) => total_cmp_f64(*v as f64, *w),
417 (Number::Float(v), Number::Int(w)) => total_cmp_f64(*v, *w as f64),
418 (Number::Int(v), Number::Decimal(w)) => Decimal::from(*v).cmp(w),
420 (Number::Decimal(v), Number::Int(w)) => v.cmp(&Decimal::from(*w)),
421 (Number::Float(v), Number::Decimal(w)) => {
423 total_cmp_f64(*v, w.to_f64().unwrap())
425 }
426 (Number::Decimal(v), Number::Float(w)) => total_cmp_f64(v.to_f64().unwrap(), *w),
427 }
428 }
429}
430
431impl hash::Hash for Number {
434 fn hash<H: hash::Hasher>(&self, state: &mut H) {
435 match self {
436 Number::Int(v) => v.hash(state),
437 Number::Float(v) => v.to_bits().hash(state),
438 Number::Decimal(v) => v.hash(state),
439 }
440 }
441}
442
443impl PartialEq for Number {
444 fn eq(&self, other: &Self) -> bool {
445 fn total_eq_f64(a: f64, b: f64) -> bool {
446 a.to_bits().eq(&b.to_bits()) || (a == 0.0 && b == 0.0)
447 }
448
449 match (self, other) {
450 (Number::Int(v), Number::Int(w)) => v.eq(w),
451 (Number::Float(v), Number::Float(w)) => total_eq_f64(*v, *w),
452 (Number::Decimal(v), Number::Decimal(w)) => v.eq(w),
453 (Number::Int(v), Number::Float(w)) => total_eq_f64(*v as f64, *w),
455 (Number::Float(v), Number::Int(w)) => total_eq_f64(*v, *w as f64),
456 (Number::Int(v), Number::Decimal(w)) => Decimal::from(*v).eq(w),
458 (Number::Decimal(v), Number::Int(w)) => v.eq(&Decimal::from(*w)),
459 (Number::Float(v), Number::Decimal(w)) => total_eq_f64(*v, w.to_f64().unwrap()),
461 (Number::Decimal(v), Number::Float(w)) => total_eq_f64(v.to_f64().unwrap(), *w),
462 }
463 }
464}
465
466impl PartialOrd for Number {
467 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
468 Some(self.cmp(other))
469 }
470}
471
472macro_rules! impl_simple_try_op {
473 ($trt:ident, $fn:ident, $unchecked:ident, $checked:ident) => {
474 impl $trt for Number {
475 type Output = Self;
476 fn $fn(self, other: Self) -> Result<Self, Error> {
477 Ok(match (self, other) {
478 (Number::Int(v), Number::Int(w)) => Number::Int(
479 v.$checked(w).ok_or_else(|| Error::$trt(v.to_string(), w.to_string()))?,
480 ),
481 (Number::Float(v), Number::Float(w)) => Number::Float(v.$unchecked(w)),
482 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(
483 v.$checked(w).ok_or_else(|| Error::$trt(v.to_string(), w.to_string()))?,
484 ),
485 (Number::Int(v), Number::Float(w)) => Number::Float((v as f64).$unchecked(w)),
486 (Number::Float(v), Number::Int(w)) => Number::Float(v.$unchecked(w as f64)),
487 (v, w) => Number::Decimal(
488 v.to_decimal()
489 .$checked(w.to_decimal())
490 .ok_or_else(|| Error::$trt(v.to_string(), w.to_string()))?,
491 ),
492 })
493 }
494 }
495 };
496}
497
498impl_simple_try_op!(TryAdd, try_add, add, checked_add);
499impl_simple_try_op!(TrySub, try_sub, sub, checked_sub);
500impl_simple_try_op!(TryMul, try_mul, mul, checked_mul);
501impl_simple_try_op!(TryDiv, try_div, div, checked_div);
502
503impl TryPow for Number {
504 type Output = Self;
505 fn try_pow(self, power: Self) -> Result<Self, Error> {
506 Ok(match (self, power) {
507 (Self::Int(v), Self::Int(p)) => Self::Int(match v {
508 0 => match p.cmp(&0) {
509 Ordering::Less => return Err(Error::TryPow(v.to_string(), p.to_string())),
511 Ordering::Equal => 1,
513 Ordering::Greater => 0,
515 },
516 1 => 1,
518 -1 => {
519 if p % 2 == 0 {
520 1
522 } else {
523 -1
525 }
526 }
527 _ => p
529 .try_into()
530 .ok()
531 .and_then(|p| v.checked_pow(p))
532 .ok_or_else(|| Error::TryPow(v.to_string(), p.to_string()))?,
533 }),
534 (Self::Decimal(v), Self::Int(p)) => Self::Decimal(
535 v.checked_powi(p).ok_or_else(|| Error::TryPow(v.to_string(), p.to_string()))?,
536 ),
537 (Self::Decimal(v), Self::Float(p)) => Self::Decimal(
538 v.checked_powf(p).ok_or_else(|| Error::TryPow(v.to_string(), p.to_string()))?,
539 ),
540 (Self::Decimal(v), Self::Decimal(p)) => Self::Decimal(
541 v.checked_powd(p).ok_or_else(|| Error::TryPow(v.to_string(), p.to_string()))?,
542 ),
543 (v, p) => v.as_float().powf(p.as_float()).into(),
544 })
545 }
546}
547
548impl TryNeg for Number {
549 type Output = Self;
550
551 fn try_neg(self) -> Result<Self::Output, Error> {
552 Ok(match self {
553 Self::Int(n) => {
554 Number::Int(n.checked_neg().ok_or_else(|| Error::TryNeg(n.to_string()))?)
555 }
556 Self::Float(n) => Number::Float(-n),
557 Self::Decimal(n) => Number::Decimal(-n),
558 })
559 }
560}
561
562impl ops::Add for Number {
563 type Output = Self;
564 fn add(self, other: Self) -> Self {
565 match (self, other) {
566 (Number::Int(v), Number::Int(w)) => Number::Int(v + w),
567 (Number::Float(v), Number::Float(w)) => Number::Float(v + w),
568 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v + w),
569 (Number::Int(v), Number::Float(w)) => Number::Float(v as f64 + w),
570 (Number::Float(v), Number::Int(w)) => Number::Float(v + w as f64),
571 (v, w) => Number::from(v.as_decimal() + w.as_decimal()),
572 }
573 }
574}
575
576impl<'a, 'b> ops::Add<&'b Number> for &'a Number {
577 type Output = Number;
578 fn add(self, other: &'b Number) -> Number {
579 match (self, other) {
580 (Number::Int(v), Number::Int(w)) => Number::Int(v + w),
581 (Number::Float(v), Number::Float(w)) => Number::Float(v + w),
582 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v + w),
583 (Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 + w),
584 (Number::Float(v), Number::Int(w)) => Number::Float(v + *w as f64),
585 (v, w) => Number::from(v.to_decimal() + w.to_decimal()),
586 }
587 }
588}
589
590impl ops::Sub for Number {
591 type Output = Self;
592 fn sub(self, other: Self) -> Self {
593 match (self, other) {
594 (Number::Int(v), Number::Int(w)) => Number::Int(v - w),
595 (Number::Float(v), Number::Float(w)) => Number::Float(v - w),
596 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v - w),
597 (Number::Int(v), Number::Float(w)) => Number::Float(v as f64 - w),
598 (Number::Float(v), Number::Int(w)) => Number::Float(v - w as f64),
599 (v, w) => Number::from(v.as_decimal() - w.as_decimal()),
600 }
601 }
602}
603
604impl<'a, 'b> ops::Sub<&'b Number> for &'a Number {
605 type Output = Number;
606 fn sub(self, other: &'b Number) -> Number {
607 match (self, other) {
608 (Number::Int(v), Number::Int(w)) => Number::Int(v - w),
609 (Number::Float(v), Number::Float(w)) => Number::Float(v - w),
610 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v - w),
611 (Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 - w),
612 (Number::Float(v), Number::Int(w)) => Number::Float(v - *w as f64),
613 (v, w) => Number::from(v.to_decimal() - w.to_decimal()),
614 }
615 }
616}
617
618impl ops::Mul for Number {
619 type Output = Self;
620 fn mul(self, other: Self) -> Self {
621 match (self, other) {
622 (Number::Int(v), Number::Int(w)) => Number::Int(v * w),
623 (Number::Float(v), Number::Float(w)) => Number::Float(v * w),
624 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v * w),
625 (Number::Int(v), Number::Float(w)) => Number::Float(v as f64 * w),
626 (Number::Float(v), Number::Int(w)) => Number::Float(v * w as f64),
627 (v, w) => Number::from(v.as_decimal() * w.as_decimal()),
628 }
629 }
630}
631
632impl<'a, 'b> ops::Mul<&'b Number> for &'a Number {
633 type Output = Number;
634 fn mul(self, other: &'b Number) -> Number {
635 match (self, other) {
636 (Number::Int(v), Number::Int(w)) => Number::Int(v * w),
637 (Number::Float(v), Number::Float(w)) => Number::Float(v * w),
638 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v * w),
639 (Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 * w),
640 (Number::Float(v), Number::Int(w)) => Number::Float(v * *w as f64),
641 (v, w) => Number::from(v.to_decimal() * w.to_decimal()),
642 }
643 }
644}
645
646impl ops::Div for Number {
647 type Output = Self;
648 fn div(self, other: Self) -> Self {
649 match (self, other) {
650 (Number::Int(v), Number::Int(w)) => Number::Int(v / w),
651 (Number::Float(v), Number::Float(w)) => Number::Float(v / w),
652 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v / w),
653 (Number::Int(v), Number::Float(w)) => Number::Float(v as f64 / w),
654 (Number::Float(v), Number::Int(w)) => Number::Float(v / w as f64),
655 (v, w) => Number::from(v.as_decimal() / w.as_decimal()),
656 }
657 }
658}
659
660impl<'a, 'b> ops::Div<&'b Number> for &'a Number {
661 type Output = Number;
662 fn div(self, other: &'b Number) -> Number {
663 match (self, other) {
664 (Number::Int(v), Number::Int(w)) => Number::Int(v / w),
665 (Number::Float(v), Number::Float(w)) => Number::Float(v / w),
666 (Number::Decimal(v), Number::Decimal(w)) => Number::Decimal(v / w),
667 (Number::Int(v), Number::Float(w)) => Number::Float(*v as f64 / w),
668 (Number::Float(v), Number::Int(w)) => Number::Float(v / *w as f64),
669 (v, w) => Number::from(v.to_decimal() / w.to_decimal()),
670 }
671 }
672}
673
674impl Neg for Number {
675 type Output = Self;
676
677 fn neg(self) -> Self::Output {
678 match self {
679 Self::Int(n) => Number::Int(-n),
680 Self::Float(n) => Number::Float(-n),
681 Self::Decimal(n) => Number::Decimal(-n),
682 }
683 }
684}
685
686impl Sum<Self> for Number {
689 fn sum<I>(iter: I) -> Number
690 where
691 I: Iterator<Item = Self>,
692 {
693 iter.fold(Number::Int(0), |a, b| a + b)
694 }
695}
696
697impl<'a> Sum<&'a Self> for Number {
698 fn sum<I>(iter: I) -> Number
699 where
700 I: Iterator<Item = &'a Self>,
701 {
702 iter.fold(Number::Int(0), |a, b| &a + b)
703 }
704}
705
706impl Product<Self> for Number {
707 fn product<I>(iter: I) -> Number
708 where
709 I: Iterator<Item = Self>,
710 {
711 iter.fold(Number::Int(1), |a, b| a * b)
712 }
713}
714
715impl<'a> Product<&'a Self> for Number {
716 fn product<I>(iter: I) -> Number
717 where
718 I: Iterator<Item = &'a Self>,
719 {
720 iter.fold(Number::Int(1), |a, b| &a * b)
721 }
722}
723
724pub struct Sorted<T>(pub T);
725
726pub trait Sort {
727 fn sorted(&mut self) -> Sorted<&Self>
728 where
729 Self: Sized;
730}
731
732impl Sort for Vec<Number> {
733 fn sorted(&mut self) -> Sorted<&Vec<Number>> {
734 self.sort();
735 Sorted(self)
736 }
737}