Skip to main content

pipa/builtins/
parse.rs

1use crate::runtime::context::JSContext;
2use crate::value::JSValue;
3
4pub fn global_parseint(ctx: &mut JSContext, args: &[JSValue]) -> JSValue {
5    if args.is_empty() {
6        return JSValue::new_float(f64::NAN);
7    }
8    let s = if args[0].is_string() {
9        ctx.get_atom_str(args[0].get_atom())
10    } else if args[0].is_int() {
11        return args[0];
12    } else if args[0].is_float() {
13        return JSValue::new_int(args[0].get_float().trunc() as i64);
14    } else {
15        return JSValue::new_float(f64::NAN);
16    };
17
18    let mut input = s.trim_start();
19    let mut sign = 1i64;
20    if let Some(rest) = input.strip_prefix('-') {
21        sign = -1;
22        input = rest;
23    } else if let Some(rest) = input.strip_prefix('+') {
24        input = rest;
25    }
26
27    let mut radix = if args.len() > 1 {
28        if args[1].is_int() {
29            args[1].get_int() as i32
30        } else if args[1].is_float() {
31            args[1].get_float() as i32
32        } else {
33            0
34        }
35    } else {
36        0
37    };
38
39    if radix != 0 && !(2..=36).contains(&radix) {
40        return JSValue::new_float(f64::NAN);
41    }
42
43    if radix == 0 {
44        if input.starts_with("0x") || input.starts_with("0X") {
45            radix = 16;
46            input = &input[2..];
47        } else {
48            radix = 10;
49        }
50    } else if radix == 16 && (input.starts_with("0x") || input.starts_with("0X")) {
51        input = &input[2..];
52    }
53
54    let mut digits = String::new();
55    for ch in input.chars() {
56        if ch.to_digit(radix as u32).is_some() {
57            digits.push(ch);
58        } else {
59            break;
60        }
61    }
62
63    if digits.is_empty() {
64        return JSValue::new_float(f64::NAN);
65    }
66
67    match i64::from_str_radix(&digits, radix as u32) {
68        Ok(v) => JSValue::new_int(sign.saturating_mul(v)),
69        Err(_) => JSValue::new_float(f64::NAN),
70    }
71}
72
73pub fn global_parsefloat(ctx: &mut JSContext, args: &[JSValue]) -> JSValue {
74    if args.is_empty() {
75        return JSValue::new_float(f64::NAN);
76    }
77    let s = if args[0].is_string() {
78        ctx.get_atom_str(args[0].get_atom())
79    } else if args[0].is_float() || args[0].is_int() {
80        return args[0];
81    } else {
82        return JSValue::new_float(f64::NAN);
83    };
84    match s.trim().parse::<f64>() {
85        Ok(v) => JSValue::new_float(v),
86        Err(_) => JSValue::new_float(f64::NAN),
87    }
88}