1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use super::*;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};

impl Hash for Number {
    fn hash<H>(&self, hasher: &mut H)
    where
        H: Hasher,
    {
        self.discriminant().hash(hasher);
        match *self {
            Number::U8(v) => v.hash(hasher),
            Number::U16(v) => v.hash(hasher),
            Number::U32(v) => v.hash(hasher),
            Number::U64(v) => v.hash(hasher),
            Number::U128(v) => v.hash(hasher),
            Number::I8(v) => v.hash(hasher),
            Number::I16(v) => v.hash(hasher),
            Number::I32(v) => v.hash(hasher),
            Number::I64(v) => v.hash(hasher),
            Number::I128(v) => v.hash(hasher),
            Number::F32(v) => OrderedFloat(v).hash(hasher),
            Number::F64(v) => OrderedFloat(v).hash(hasher),
        }
    }
}

impl Eq for Number {}

impl PartialOrd for Number {
    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
        Some(self.cmp(rhs))
    }
}

impl Ord for Number {
    fn cmp(&self, rhs: &Self) -> Ordering {
        match (self, rhs) {
            (Number::I128(i), n) => i.cmp(&i128::from(n)),
            (Number::U128(i), n) => i.cmp(&u128::from(n)),
            (Number::F64(i), n) => OrderedFloat(*i).cmp(&OrderedFloat(f64::from(n))),
            (Number::I64(i), n) => i.cmp(&i64::from(n)),
            (Number::U64(i), n) => i.cmp(&u64::from(n)),
            (Number::F32(i), n) => OrderedFloat(*i).cmp(&OrderedFloat(f32::from(n))),
            (Number::I32(i), n) => i.cmp(&i32::from(n)),
            (Number::U32(i), n) => i.cmp(&u32::from(n)),
            (Number::I16(i), n) => i.cmp(&i16::from(n)),
            (Number::U16(i), n) => i.cmp(&u16::from(n)),
            (Number::I8(i), n) => i.cmp(&i8::from(n)),
            (Number::U8(i), n) => i.cmp(&u8::from(n)),
        }
    }
}

impl std::ops::Add<Number> for Number {
    type Output = Number;

    fn add(self, rhs: Number) -> Number {
        match (self, rhs) {
            (Number::I128(i), n) => (i + i128::from(n)).into(),
            (Number::U128(i), n) => (i + u128::from(n)).into(),
            (Number::F64(i), n) => (i + f64::from(n)).into(),
            (Number::I64(i), n) => (i + i64::from(n)).into(),
            (Number::U64(i), n) => (i + u64::from(n)).into(),
            (Number::F32(i), n) => (i + f32::from(n)).into(),
            (Number::I32(i), n) => (i + i32::from(n)).into(),
            (Number::U32(i), n) => (i + u32::from(n)).into(),
            (Number::I16(i), n) => (i + i16::from(n)).into(),
            (Number::U16(i), n) => (i + u16::from(n)).into(),
            (Number::I8(i), n) => (i + i8::from(n)).into(),
            (Number::U8(i), n) => (i + u8::from(n)).into(),
        }
    }
}

impl PartialEq<Number> for Number {
    fn eq(&self, rhs: &Number) -> bool {
        match (self, rhs) {
            (Number::I128(i), n) => i == &i128::from(n),
            (Number::U128(i), n) => i == &u128::from(n),
            (Number::F64(i), n) => OrderedFloat(*i) == OrderedFloat(f64::from(n)),
            (Number::I64(i), n) => i == &i64::from(n),
            (Number::U64(i), n) => i == &u64::from(n),
            (Number::F32(i), n) => OrderedFloat(*i) == OrderedFloat(f32::from(n)),
            (Number::I32(i), n) => i == &i32::from(n),
            (Number::U32(i), n) => i == &u32::from(n),
            (Number::I16(i), n) => i == &i16::from(n),
            (Number::U16(i), n) => i == &u16::from(n),
            (Number::I8(i), n) => i == &i8::from(n),
            (Number::U8(i), n) => i == &u8::from(n),
        }
    }
}

impl<T: UnstructuredDataTrait> PartialEq<Unstructured<T>> for Number {
    fn eq(&self, rhs: &Unstructured<T>) -> bool {
        match (rhs, self) {
            (Unstructured::<T>::Number(n1), n2) => n1 == n2,
            (Unstructured::<T>::Option(Some(n1)), n2) => &**n1 == n2,
            (Unstructured::<T>::Newtype(n1), n2) => &**n1 == n2,
            _ => false,
        }
    }
}

macro_rules! impl_partial_eq_number {
    ( $( $type:ty )* ) => {
        $(
            impl PartialEq<Number> for $type {
                fn eq(&self, rhs: &Number) -> bool {
                    &Number::from(self) == rhs
                }
            }

            impl PartialEq<$type> for Number {
                fn eq(&self, rhs: & $type) -> bool {
                    &Number::from(rhs) == self
                }
            }
        )*
    };
}
impl_partial_eq_number! { u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 }