oxc_ecmascript/
to_big_int.rs1use num_bigint::BigInt;
2use num_traits::{Num, One, Zero};
3
4use oxc_ast::ast::{BigIntLiteral, Expression};
5use oxc_syntax::operator::UnaryOperator;
6
7use crate::{GlobalContext, StringToBigInt, ToBoolean, ToJsString};
8
9pub trait ToBigInt<'a> {
13 fn to_big_int(&self, ctx: &impl GlobalContext<'a>) -> Option<BigInt>;
14}
15
16impl<'a> ToBigInt<'a> for Expression<'a> {
17 #[expect(clippy::cast_possible_truncation)]
18 fn to_big_int(&self, ctx: &impl GlobalContext<'a>) -> Option<BigInt> {
19 match self {
20 Expression::NumericLiteral(number_literal) => {
21 let value = number_literal.value;
22 if value.abs() < 2_f64.powi(53) && value.fract() == 0.0 {
23 Some(BigInt::from(value as i64))
24 } else {
25 None
26 }
27 }
28 Expression::BigIntLiteral(lit) => lit.to_big_int(ctx),
29 Expression::BooleanLiteral(bool_literal) => {
30 if bool_literal.value {
31 Some(BigInt::one())
32 } else {
33 Some(BigInt::zero())
34 }
35 }
36 Expression::UnaryExpression(unary_expr) => match unary_expr.operator {
37 UnaryOperator::LogicalNot => self
38 .to_boolean(ctx)
39 .map(|boolean| if boolean { BigInt::one() } else { BigInt::zero() }),
40 UnaryOperator::UnaryNegation => {
41 unary_expr.argument.to_big_int(ctx).map(std::ops::Neg::neg)
42 }
43 UnaryOperator::BitwiseNot => {
44 unary_expr.argument.to_big_int(ctx).map(std::ops::Not::not)
45 }
46 UnaryOperator::UnaryPlus => unary_expr.argument.to_big_int(ctx),
47 _ => None,
48 },
49 Expression::StringLiteral(string_literal) => {
50 string_literal.value.as_str().string_to_big_int()
51 }
52 Expression::TemplateLiteral(_) => {
53 self.to_js_string(ctx).and_then(|value| value.as_ref().string_to_big_int())
54 }
55 _ => None,
56 }
57 }
58}
59
60impl<'a> ToBigInt<'a> for BigIntLiteral<'a> {
61 fn to_big_int(&self, _ctx: &impl GlobalContext<'a>) -> Option<BigInt> {
62 let value = BigInt::from_str_radix(&self.value, 10).ok();
64 debug_assert!(value.is_some(), "Failed to parse {}n", self.value);
65 value
66 }
67}