quickjs_runtime/quickjs_utils/
bigints.rs

1use crate::jsutils::JsError;
2use crate::quickjs_utils;
3use crate::quickjs_utils::{functions, primitives};
4use crate::quickjsrealmadapter::QuickJsRealmAdapter;
5use crate::quickjsvalueadapter::QuickJsValueAdapter;
6#[cfg(feature = "bellard")]
7use crate::quickjsvalueadapter::TAG_BIG_INT;
8use libquickjs_sys as q;
9
10pub fn new_bigint_i64_q(
11    context: &QuickJsRealmAdapter,
12    int: i64,
13) -> Result<QuickJsValueAdapter, JsError> {
14    unsafe { new_bigint_i64(context.context, int) }
15}
16
17pub fn new_bigint_u64_q(
18    context: &QuickJsRealmAdapter,
19    int: u64,
20) -> Result<QuickJsValueAdapter, JsError> {
21    unsafe { new_bigint_u64(context.context, int) }
22}
23
24#[allow(dead_code)]
25/// # Safety
26/// When passing a context pointer please make sure the corresponding QuickJsContext is still valid
27pub unsafe fn new_bigint_i64(
28    context: *mut q::JSContext,
29    int: i64,
30) -> Result<QuickJsValueAdapter, JsError> {
31    let res_val = q::JS_NewBigInt64(context, int);
32    let ret = QuickJsValueAdapter::new(context, res_val, false, true, "new_bigint_i64");
33
34    #[cfg(feature = "bellard")]
35    {
36        #[cfg(debug_assertions)]
37        if ret.get_tag() == TAG_BIG_INT {
38            assert_eq!(ret.get_ref_count(), 1);
39        }
40    }
41    Ok(ret)
42}
43
44#[allow(dead_code)]
45/// # Safety
46/// When passing a context pointer please make sure the corresponding QuickJsContext is still valid
47pub unsafe fn new_bigint_u64(
48    context: *mut q::JSContext,
49    int: u64,
50) -> Result<QuickJsValueAdapter, JsError> {
51    let res_val = q::JS_NewBigUint64(context, int);
52    let ret = QuickJsValueAdapter::new(context, res_val, false, true, "new_bigint_u64");
53
54    #[cfg(feature = "bellard")]
55    {
56        #[cfg(debug_assertions)]
57        if ret.get_tag() == TAG_BIG_INT {
58            assert_eq!(ret.get_ref_count(), 1);
59        }
60    }
61    Ok(ret)
62}
63
64pub fn new_bigint_str_q(
65    context: &QuickJsRealmAdapter,
66    input_str: &str,
67) -> Result<QuickJsValueAdapter, JsError> {
68    unsafe { new_bigint_str(context.context, input_str) }
69}
70
71#[allow(dead_code)]
72/// # Safety
73/// When passing a context pointer please make sure the corresponding QuickJsContext is still valid
74pub unsafe fn new_bigint_str(
75    context: *mut q::JSContext,
76    input_str: &str,
77) -> Result<QuickJsValueAdapter, JsError> {
78    let global_ref = quickjs_utils::get_global(context);
79    let str_ref = primitives::from_string(context, input_str)?;
80    let bigint_ref = functions::invoke_member_function(context, &global_ref, "BigInt", &[str_ref])?;
81    let ret = bigint_ref;
82
83    #[cfg(feature = "bellard")]
84    assert_eq!(ret.get_ref_count(), 1);
85    Ok(ret)
86}
87
88pub fn to_string_q(
89    context: &QuickJsRealmAdapter,
90    big_int_ref: &QuickJsValueAdapter,
91) -> Result<String, JsError> {
92    unsafe { to_string(context.context, big_int_ref) }
93}
94
95#[allow(dead_code)]
96/// # Safety
97/// When passing a context pointer please make sure the corresponding QuickJsContext is still valid
98pub unsafe fn to_string(
99    context: *mut q::JSContext,
100    big_int_ref: &QuickJsValueAdapter,
101) -> Result<String, JsError> {
102    if !big_int_ref.is_big_int() {
103        return Err(JsError::new_str("big_int_ref was not a big_int"));
104    }
105    functions::call_to_string(context, big_int_ref)
106}
107
108#[cfg(test)]
109pub mod tests {
110    use crate::facades::tests::init_test_rt;
111    use crate::jsutils::Script;
112    use crate::quickjs_utils::bigints;
113    use crate::quickjs_utils::bigints::new_bigint_str_q;
114
115    #[test]
116    fn test_bigint() {
117        let rt = init_test_rt();
118        rt.exe_rt_task_in_event_loop(|q_js_rt| {
119            let q_ctx = q_js_rt.get_main_realm();
120
121            let res = q_ctx
122                .eval(Script::new("createABigInt.js", "BigInt(1234567890)"))
123                .expect("script failed");
124            log::info!(
125                "script bi was {} {}",
126                res.get_tag(),
127                res.to_string().expect("could not toString")
128            );
129
130            let bi_ref = bigints::new_bigint_u64_q(q_ctx, 659863456456)
131                .expect("could not create bigint from u64");
132
133            unsafe {
134                if let Some(e) = crate::quickjs_utils::errors::get_exception(q_ctx.context) {
135                    log::error!("ex: {}", e);
136                }
137            }
138
139            let to_str = bigints::to_string_q(q_ctx, &bi_ref).expect("could not tostring bigint");
140            assert_eq!(to_str, "659863456456");
141            let bi_ref = bigints::new_bigint_i64_q(q_ctx, 659863456457)
142                .expect("could not create bigint from u64");
143            let to_str = bigints::to_string_q(q_ctx, &bi_ref).expect("could not tostring bigint");
144            assert_eq!(to_str, "659863456457");
145
146            let bi_ref =
147                new_bigint_str_q(q_ctx, "345346345645234564536345345345345456534783448567")
148                    .expect("could not create bigint from str");
149
150            log::debug!("bi_ref.get_js_type is {}", bi_ref.get_js_type());
151
152            let to_str = bigints::to_string_q(q_ctx, &bi_ref).expect("could not tostring bigint");
153            assert_eq!(to_str, "345346345645234564536345345345345456534783448567");
154        });
155    }
156}