enum_ordinalize_derive/
int128.rs

1use core::{
2    cmp::Ordering,
3    fmt::{self, Display, Formatter},
4    num::ParseIntError,
5    ops::Neg,
6    str::FromStr,
7};
8
9#[derive(Debug, Copy, Eq, Clone)]
10pub(crate) enum Int128 {
11    Signed(i128),
12    Unsigned(u128),
13}
14
15impl PartialEq for Int128 {
16    #[inline]
17    fn eq(&self, other: &Int128) -> bool {
18        match self {
19            Self::Signed(i) => match other {
20                Self::Signed(i2) => i.eq(i2),
21                Self::Unsigned(u2) => {
22                    if i.is_negative() {
23                        false
24                    } else {
25                        (*i as u128).eq(u2)
26                    }
27                },
28            },
29            Self::Unsigned(u) => match other {
30                Self::Signed(i2) => {
31                    if i2.is_negative() {
32                        false
33                    } else {
34                        u.eq(&(*i2 as u128))
35                    }
36                },
37                Self::Unsigned(u2) => u.eq(u2),
38            },
39        }
40    }
41}
42
43impl PartialOrd for Int128 {
44    #[inline]
45    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
46        Some(self.cmp(other))
47    }
48}
49
50impl Ord for Int128 {
51    #[inline]
52    fn cmp(&self, other: &Self) -> Ordering {
53        match self {
54            Self::Signed(i) => match other {
55                Self::Signed(i2) => i.cmp(i2),
56                Self::Unsigned(u2) => {
57                    if i.is_negative() {
58                        Ordering::Less
59                    } else {
60                        (*i as u128).cmp(u2)
61                    }
62                },
63            },
64            Self::Unsigned(u) => match other {
65                Self::Signed(i2) => {
66                    if i2.is_negative() {
67                        Ordering::Greater
68                    } else {
69                        u.cmp(&(*i2 as u128))
70                    }
71                },
72                Self::Unsigned(u2) => u.cmp(u2),
73            },
74        }
75    }
76}
77
78impl Display for Int128 {
79    #[inline]
80    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
81        match self {
82            Self::Signed(i) => Display::fmt(i, f),
83            Self::Unsigned(u) => Display::fmt(u, f),
84        }
85    }
86}
87
88impl Default for Int128 {
89    #[inline]
90    fn default() -> Self {
91        Self::ZERO
92    }
93}
94
95impl Int128 {
96    pub(crate) const ZERO: Self = Self::Unsigned(0);
97}
98
99macro_rules! impl_from_signed {
100    (@inner $t: ty) => {
101        impl From<$t> for Int128 {
102            #[inline]
103            fn from(value: $t) -> Self {
104                Int128::Signed(value as i128)
105            }
106        }
107    };
108    ($($t: ty),+ $(,)*) => {
109        $(
110            impl_from_signed!(@inner $t);
111        )*
112    };
113}
114
115impl_from_signed!(i8, i16, i32, i64, i128, isize);
116
117impl FromStr for Int128 {
118    type Err = ParseIntError;
119
120    #[inline]
121    fn from_str(s: &str) -> Result<Self, Self::Err> {
122        if s.starts_with('-') {
123            Ok(Self::Signed(s.parse()?))
124        } else {
125            Ok(Self::Unsigned(s.parse()?))
126        }
127    }
128}
129
130impl Neg for Int128 {
131    type Output = Int128;
132
133    fn neg(self) -> Self::Output {
134        match self {
135            Self::Signed(i) => {
136                if i == i128::MIN {
137                    Self::Unsigned(1 << 127)
138                } else {
139                    Self::Signed(-i)
140                }
141            },
142            Self::Unsigned(u) => match u.cmp(&(1 << 127)) {
143                Ordering::Equal => Self::Signed(i128::MIN),
144                Ordering::Less => Self::Signed(-(u as i128)),
145                Ordering::Greater => panic!("-{} is experiencing an overflow", u),
146            },
147        }
148    }
149}
150
151impl Int128 {
152    #[inline]
153    pub(crate) fn inc(&mut self) {
154        match self {
155            Self::Signed(i) => {
156                if *i == i128::MAX {
157                    *self = Self::Unsigned(1 << 127)
158                } else {
159                    *i += 1;
160                }
161            },
162            Self::Unsigned(u) => {
163                *u = u.saturating_add(1);
164            },
165        }
166    }
167}