quickjs_rusty/value/
bigint.rs

1use num_traits::cast::ToPrimitive;
2
3#[derive(Clone, Debug)]
4pub enum BigIntOrI64 {
5    Int(i64),
6    BigInt(num_bigint::BigInt),
7}
8
9impl PartialEq for BigIntOrI64 {
10    fn eq(&self, other: &Self) -> bool {
11        use BigIntOrI64::*;
12        match (&self, &other) {
13            (Int(i), Int(j)) => i == j,
14            (Int(i), BigInt(b)) | (BigInt(b), Int(i)) => b == &num_bigint::BigInt::from(*i),
15            (BigInt(a), BigInt(b)) => a == b,
16        }
17    }
18}
19
20impl Eq for BigIntOrI64 {}
21
22/// A value holding JavaScript
23/// [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) type
24#[derive(Clone, Debug, PartialEq, Eq)]
25pub struct BigInt {
26    pub(crate) inner: BigIntOrI64,
27}
28
29impl BigInt {
30    /// Return `Some` if value fits into `i64` and `None` otherwise
31    pub fn as_i64(&self) -> Option<i64> {
32        match &self.inner {
33            BigIntOrI64::Int(int) => Some(*int),
34            BigIntOrI64::BigInt(bigint) => bigint.to_i64(),
35        }
36    }
37    /// Convert value into `num_bigint::BigInt`
38    pub fn into_bigint(self) -> num_bigint::BigInt {
39        match self.inner {
40            BigIntOrI64::Int(int) => int.into(),
41            BigIntOrI64::BigInt(bigint) => bigint,
42        }
43    }
44}
45
46impl std::fmt::Display for BigInt {
47    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
48        match self.inner {
49            BigIntOrI64::Int(i) => write!(f, "{}", i),
50            BigIntOrI64::BigInt(ref i) => write!(f, "{}", i),
51        }
52    }
53}
54
55impl From<i64> for BigInt {
56    fn from(int: i64) -> Self {
57        BigInt {
58            inner: BigIntOrI64::Int(int),
59        }
60    }
61}
62
63impl From<num_bigint::BigInt> for BigInt {
64    fn from(bigint: num_bigint::BigInt) -> Self {
65        BigInt {
66            inner: BigIntOrI64::BigInt(bigint),
67        }
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    #[allow(unused_imports)]
74    use super::*;
75
76    #[test]
77    fn test_bigint_as_i64() {
78        let value = BigInt {
79            inner: BigIntOrI64::Int(1234i64),
80        };
81        assert_eq!(value.as_i64(), Some(1234i64));
82    }
83
84    #[test]
85    fn test_bigint_as_i64_overflow() {
86        let value = BigInt {
87            inner: BigIntOrI64::BigInt(num_bigint::BigInt::from(std::i128::MAX)),
88        };
89        assert_eq!(value.as_i64(), None);
90    }
91
92    #[test]
93    fn test_bigint_into_bigint() {
94        for i in [
95            0_i128,
96            std::i64::MAX as i128,
97            std::i64::MIN as i128,
98            std::i128::MAX,
99            std::i128::MIN,
100        ] {
101            let value = BigInt {
102                inner: BigIntOrI64::BigInt(num_bigint::BigInt::from(i)),
103            };
104            assert_eq!(value.into_bigint(), num_bigint::BigInt::from(i));
105        }
106    }
107}