1use std::cmp;
2use std::cmp::Ordering;
3use std::fmt::{self, Debug, Display, LowerHex, UpperHex};
4use std::ops;
5
6#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
7pub(crate) enum IntPriv {
8 PosInt(u64),
10 NegInt(i64),
12}
13
14#[derive(Copy, Clone, PartialEq, Eq, Hash)]
18pub struct Integer {
19 n: IntPriv,
20}
21
22impl Integer {
23 pub fn min_value() -> Integer {
25 Integer {
26 n: IntPriv::NegInt(i64::min_value()),
27 }
28 }
29
30 pub fn max_value() -> Integer {
32 Integer {
33 n: IntPriv::PosInt(u64::max_value()),
34 }
35 }
36
37 #[inline]
39 pub fn is_i64(&self) -> bool {
40 match self.n {
41 IntPriv::PosInt(n) => n <= ::std::i64::MAX as u64,
42 IntPriv::NegInt(..) => true,
43 }
44 }
45
46 #[inline]
48 pub fn is_u64(&self) -> bool {
49 match self.n {
50 IntPriv::PosInt(..) => true,
51 IntPriv::NegInt(..) => false,
52 }
53 }
54
55 #[inline]
57 pub fn as_i64(&self) -> Option<i64> {
58 match self.n {
59 IntPriv::PosInt(n) => i64::try_from(n).ok(),
60 IntPriv::NegInt(n) => Some(n),
61 }
62 }
63
64 #[inline]
66 pub fn as_u64(&self) -> Option<u64> {
67 match self.n {
68 IntPriv::PosInt(n) => Some(n),
69 IntPriv::NegInt(n) => u64::try_from(n).ok(),
70 }
71 }
72
73 #[inline]
75 pub fn as_bits(&self) -> u64 {
76 match self.n {
77 IntPriv::PosInt(n) => n,
78 IntPriv::NegInt(n) => n as u64,
79 }
80 }
81}
82
83pub(crate) fn get_int_internal(val: &Integer) -> IntPriv {
84 val.n
85}
86
87impl std::default::Default for Integer {
88 fn default() -> Self {
89 Self {
90 n: IntPriv::PosInt(0),
91 }
92 }
93}
94
95impl cmp::Ord for Integer {
96 fn cmp(&self, other: &Integer) -> Ordering {
97 match (self.n, other.n) {
98 (IntPriv::NegInt(lhs), IntPriv::NegInt(ref rhs)) => lhs.cmp(rhs),
99 (IntPriv::NegInt(_), IntPriv::PosInt(_)) => Ordering::Less,
100 (IntPriv::PosInt(_), IntPriv::NegInt(_)) => Ordering::Greater,
101 (IntPriv::PosInt(lhs), IntPriv::PosInt(ref rhs)) => lhs.cmp(rhs),
102 }
103 }
104}
105
106impl cmp::PartialOrd for Integer {
107 fn partial_cmp(&self, other: &Integer) -> Option<Ordering> {
108 Some(self.cmp(other))
109 }
110}
111
112impl ops::Add<i64> for Integer {
113 type Output = Integer;
114
115 fn add(self, other: i64) -> Integer {
116 match self.n {
117 IntPriv::PosInt(lhs) => {
118 if other >= 0 {
119 Integer::from(lhs + (other as u64))
120 } else if lhs >= (1u64 << 63) {
121 Integer::from(lhs.wrapping_add(other as u64))
122 } else {
123 Integer::from((lhs as i64) + other)
124 }
125 }
126 IntPriv::NegInt(lhs) => Integer::from(lhs + other),
127 }
128 }
129}
130
131impl ops::Sub<i64> for Integer {
132 type Output = Integer;
133
134 fn sub(self, other: i64) -> Integer {
135 match self.n {
136 IntPriv::PosInt(lhs) => {
137 if other < 0 {
138 Integer::from(lhs.wrapping_sub(other as u64))
139 } else if lhs >= (1u64 << 63) {
140 Integer::from(lhs - (other as u64))
141 } else {
142 Integer::from((lhs as i64) - other)
143 }
144 }
145 IntPriv::NegInt(lhs) => Integer::from(lhs - other),
146 }
147 }
148}
149
150impl Debug for Integer {
151 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
152 Debug::fmt(&self.n, fmt)
153 }
154}
155
156impl Display for Integer {
157 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
158 match self.n {
159 IntPriv::PosInt(v) => Display::fmt(&v, fmt),
160 IntPriv::NegInt(v) => Display::fmt(&v, fmt),
161 }
162 }
163}
164
165impl UpperHex for Integer {
166 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
167 UpperHex::fmt(&self.as_bits(), fmt)
168 }
169}
170
171impl LowerHex for Integer {
172 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
173 LowerHex::fmt(&self.as_bits(), fmt)
174 }
175}
176
177macro_rules! impl_from_unsigned {
178 ($t: ty) => {
179 impl From<$t> for Integer {
180 fn from(n: $t) -> Self {
181 Integer {
182 n: IntPriv::PosInt(n as u64),
183 }
184 }
185 }
186 };
187}
188
189macro_rules! impl_from_signed {
190 ($t: ty) => {
191 impl From<$t> for Integer {
192 fn from(n: $t) -> Self {
193 if n < 0 {
194 Integer {
195 n: IntPriv::NegInt(n as i64),
196 }
197 } else {
198 Integer {
199 n: IntPriv::PosInt(n as u64),
200 }
201 }
202 }
203 }
204 };
205}
206
207impl_from_unsigned!(u8);
208impl_from_unsigned!(u16);
209impl_from_unsigned!(u32);
210impl_from_unsigned!(u64);
211impl_from_unsigned!(usize);
212impl_from_signed!(i8);
213impl_from_signed!(i16);
214impl_from_signed!(i32);
215impl_from_signed!(i64);
216impl_from_signed!(isize);
217
218use std::convert::TryFrom;
219
220macro_rules! impl_try_from {
221 ($t: ty) => {
222 impl TryFrom<Integer> for $t {
223 type Error = Integer;
224 fn try_from(v: Integer) -> Result<Self, Self::Error> {
225 match v.n {
226 IntPriv::PosInt(n) => TryFrom::try_from(n).map_err(|_| v),
227 IntPriv::NegInt(n) => TryFrom::try_from(n).map_err(|_| v),
228 }
229 }
230 }
231 };
232}
233
234impl_try_from!(u8);
235impl_try_from!(u16);
236impl_try_from!(u32);
237impl_try_from!(u64);
238impl_try_from!(usize);
239impl_try_from!(i8);
240impl_try_from!(i16);
241impl_try_from!(i32);
242impl_try_from!(i64);
243impl_try_from!(isize);
244
245use serde::{
246 de::{Deserialize, Deserializer},
247 ser::{Serialize, Serializer},
248};
249
250impl Serialize for Integer {
251 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
252 match self.n {
253 IntPriv::PosInt(v) => serializer.serialize_u64(v),
254 IntPriv::NegInt(v) => serializer.serialize_i64(v),
255 }
256 }
257}
258
259impl<'de> Deserialize<'de> for Integer {
260 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
261 where
262 D: Deserializer<'de>,
263 {
264 struct IntVisitor;
265 impl<'de> serde::de::Visitor<'de> for IntVisitor {
266 type Value = Integer;
267
268 fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
269 write!(fmt, "an integer")
270 }
271
272 fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<Self::Value, E> {
273 Ok(Integer::from(v))
274 }
275
276 fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<Self::Value, E> {
277 Ok(Integer::from(v))
278 }
279 }
280
281 deserializer.deserialize_any(IntVisitor)
282 }
283}
284
285#[cfg(test)]
286mod tests {
287 use super::*;
288
289 #[test]
290 fn add() {
291 let x = Integer::min_value();
292 let y = i64::max_value();
293 assert_eq!(x + y, Integer::from(-1));
294 let y = 1i64;
295 assert_eq!(x + y, Integer::from(i64::min_value() + 1));
296 let x = Integer::from(1u64 << 63);
297 assert_eq!(x + y, Integer::from((1u64 << 63) + 1));
298 let x = Integer::from((1u64 << 63) - 1);
299 assert_eq!(x + y, Integer::from(1u64 << 63));
300
301 let x = Integer::max_value();
302 let y = i64::min_value();
303 assert_eq!(x + y, Integer::from(u64::max_value() >> 1));
304 let y = -1i64;
305 assert_eq!(x + y, Integer::from(u64::max_value() - 1));
306 let x = Integer::from(1u64 << 63);
307 assert_eq!(x + y, Integer::from((1u64 << 63) - 1));
308 let x = Integer::from((1u64 << 63) - 1);
309 assert_eq!(x + y, Integer::from((1u64 << 63) - 2));
310 }
311
312 #[test]
313 fn sub() {
314 let x = Integer::min_value();
315 let y = i64::min_value();
316 assert_eq!(x - y, Integer::from(0));
317 let y = -1i64;
318 assert_eq!(x - y, Integer::from(i64::min_value() + 1));
319 let x = Integer::from(1u64 << 63);
320 assert_eq!(x - y, Integer::from((1u64 << 63) + 1));
321 let x = Integer::from((1u64 << 63) - 1);
322 assert_eq!(x - y, Integer::from(1u64 << 63));
323
324 let x = Integer::max_value();
325 let y = i64::max_value();
326 assert_eq!(x - y, Integer::from(1u64 << 63));
327 let y = 1i64;
328 assert_eq!(x - y, Integer::from(u64::max_value() - 1));
329 let x = Integer::from(1u64 << 63);
330 assert_eq!(x - y, Integer::from((1u64 << 63) - 1));
331 let x = Integer::from((1u64 << 63) - 1);
332 assert_eq!(x - y, Integer::from((1u64 << 63) - 2));
333 }
334}