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
use num_traits::cast::ToPrimitive;
#[derive(Clone, Debug)]
pub enum BigIntOrI64 {
Int(i64),
BigInt(num_bigint::BigInt),
}
impl PartialEq for BigIntOrI64 {
fn eq(&self, other: &Self) -> bool {
use BigIntOrI64::*;
match (&self, &other) {
(Int(i), Int(j)) => i == j,
(Int(i), BigInt(b)) | (BigInt(b), Int(i)) => b == &num_bigint::BigInt::from(*i),
(BigInt(a), BigInt(b)) => a == b,
}
}
}
impl Eq for BigIntOrI64 {}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BigInt {
pub(crate) inner: BigIntOrI64,
}
impl BigInt {
pub fn as_i64(&self) -> Option<i64> {
match &self.inner {
BigIntOrI64::Int(int) => Some(*int),
BigIntOrI64::BigInt(bigint) => bigint.to_i64(),
}
}
pub fn into_bigint(self) -> num_bigint::BigInt {
match self.inner {
BigIntOrI64::Int(int) => int.into(),
BigIntOrI64::BigInt(bigint) => bigint,
}
}
}
impl std::fmt::Display for BigInt {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self.inner {
BigIntOrI64::Int(i) => write!(f, "{}", i),
BigIntOrI64::BigInt(ref i) => write!(f, "{}", i),
}
}
}
impl From<i64> for BigInt {
fn from(int: i64) -> Self {
BigInt {
inner: BigIntOrI64::Int(int),
}
}
}
impl From<num_bigint::BigInt> for BigInt {
fn from(bigint: num_bigint::BigInt) -> Self {
BigInt {
inner: BigIntOrI64::BigInt(bigint),
}
}
}
#[cfg(test)]
mod tests {
#[allow(unused_imports)]
use super::*;
#[test]
fn test_bigint_as_i64() {
let value = BigInt {
inner: BigIntOrI64::Int(1234i64),
};
assert_eq!(value.as_i64(), Some(1234i64));
}
#[test]
fn test_bigint_as_i64_overflow() {
let value = BigInt {
inner: BigIntOrI64::BigInt(num_bigint::BigInt::from(std::i128::MAX)),
};
assert_eq!(value.as_i64(), None);
}
#[test]
fn test_bigint_into_bigint() {
for i in vec![
0 as i128,
std::i64::MAX as i128,
std::i64::MIN as i128,
std::i128::MAX,
std::i128::MIN,
] {
let value = BigInt {
inner: BigIntOrI64::BigInt(num_bigint::BigInt::from(i)),
};
assert_eq!(value.into_bigint(), num_bigint::BigInt::from(i));
}
}
}