swc_ecma_lexer/common/lexer/
number.rs1use swc_common::BytePos;
2
3pub struct LazyInteger {
4 pub(super) start: BytePos,
5 pub(super) end: BytePos,
6 pub(super) not_octal: bool,
8 pub(super) has_underscore: bool,
9}
10
11const MAX_SAFE_INT: u64 = 9007199254740991;
12
13pub(super) fn parse_integer<const RADIX: u8>(s: &str) -> f64 {
14 debug_assert!(matches!(RADIX, 2 | 8 | 10 | 16));
15 debug_assert!(!s.is_empty());
16 debug_assert!(!s.contains('_'));
17
18 if RADIX == 10 {
19 parse_integer_from_dec(s)
20 } else if RADIX == 16 {
21 parse_integer_from_hex(s)
22 } else if RADIX == 2 {
23 parse_integer_from_bin(s)
24 } else if RADIX == 8 {
25 parse_integer_from_oct(s)
26 } else {
27 unreachable!()
28 }
29}
30
31fn parse_integer_from_hex(s: &str) -> f64 {
32 debug_assert!(s.chars().all(|c| c.is_ascii_hexdigit()));
33 const MAX_FAST_INT_LEN: usize = MAX_SAFE_INT.ilog(16) as usize;
34 if s.len() > MAX_FAST_INT_LEN {
35 s.as_bytes().iter().fold(0f64, |res, &cur| {
48 res.mul_add(
49 16.,
50 if cur < b'A' {
51 cur & 0xf
52 } else {
53 (cur & 0xf) + 9
54 } as f64,
55 )
56 })
57 } else {
58 u64::from_str_radix(s, 16).unwrap() as f64
59 }
60}
61
62fn parse_integer_from_bin(s: &str) -> f64 {
63 debug_assert!(s.chars().all(|c| c == '0' || c == '1'));
64 const MAX_FAST_INT_LEN: usize = MAX_SAFE_INT.ilog2() as usize;
65 if s.len() > MAX_FAST_INT_LEN {
66 s.as_bytes().iter().fold(0f64, |res, &cur| {
67 res.mul_add(2., if cur == b'0' { 0. } else { 1. })
68 })
69 } else {
70 u64::from_str_radix(s, 2).unwrap() as f64
71 }
72}
73
74fn parse_integer_from_oct(s: &str) -> f64 {
75 debug_assert!(s.chars().all(|c| matches!(c, '0'..='7')));
76 const MAX_FAST_INT_LEN: usize = MAX_SAFE_INT.ilog(8) as usize;
77 if s.len() > MAX_FAST_INT_LEN {
78 s.as_bytes()
79 .iter()
80 .fold(0f64, |res, &cur| res.mul_add(8., (cur - b'0') as f64))
81 } else {
82 u64::from_str_radix(s, 8).unwrap() as f64
83 }
84}
85
86fn parse_integer_from_dec(s: &str) -> f64 {
87 debug_assert!(s.chars().all(|c| c.is_ascii_digit()));
88 const MAX_FAST_INT_LEN: usize = MAX_SAFE_INT.ilog10() as usize;
89 if s.len() > MAX_FAST_INT_LEN {
90 s.parse::<f64>().unwrap()
91 } else {
92 s.parse::<u64>().unwrap() as f64
93 }
94}