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 super::BigInt;
use crate::{builtins::Number, Context, Value};
use num_traits::cast::{FromPrimitive, ToPrimitive};
use std::convert::TryFrom;
use std::str::FromStr;
impl BigInt {
#[inline]
pub(crate) fn from_string(string: &str, context: &mut Context) -> Result<Self, Value> {
if string.trim().is_empty() {
return Ok(BigInt::from(0));
}
let mut radix = 10;
let mut string = string;
if string.starts_with("0b") || string.starts_with("0B") {
radix = 2;
string = &string[2..];
}
if string.starts_with("0x") || string.starts_with("0X") {
radix = 16;
string = &string[2..];
}
if string.starts_with("0o") || string.starts_with("0O") {
radix = 8;
string = &string[2..];
}
BigInt::from_string_radix(string, radix).ok_or_else(|| {
context.construct_syntax_error(format!("cannot convert {} to a BigInt", string))
})
}
#[inline]
pub fn from_string_radix(buf: &str, radix: u32) -> Option<Self> {
num_bigint::BigInt::parse_bytes(buf.as_bytes(), radix).map(Self)
}
#[inline]
pub fn to_string_radix(&self, radix: u32) -> String {
self.0.to_str_radix(radix)
}
#[inline]
pub fn to_f64(&self) -> f64 {
self.0.to_f64().unwrap_or(std::f64::INFINITY)
}
#[inline]
pub(crate) fn from_str(string: &str) -> Option<Self> {
match num_bigint::BigInt::from_str(string) {
Ok(bigint) => Some(BigInt(bigint)),
Err(_) => None,
}
}
}
impl From<i64> for BigInt {
fn from(n: i64) -> BigInt {
BigInt(num_bigint::BigInt::from(n))
}
}
impl From<i32> for BigInt {
fn from(n: i32) -> BigInt {
BigInt(num_bigint::BigInt::from(n))
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct TryFromF64Error;
impl std::fmt::Display for TryFromF64Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Could not convert f64 value to a BigInt type")
}
}
impl TryFrom<f64> for BigInt {
type Error = TryFromF64Error;
fn try_from(n: f64) -> Result<Self, Self::Error> {
if !Number::equal(n.trunc(), n) {
return Err(TryFromF64Error);
}
match num_bigint::BigInt::from_f64(n) {
Some(bigint) => Ok(BigInt(bigint)),
None => Err(TryFromF64Error),
}
}
}