1use std::ptr;
2
3use tracing::trace;
4
5use crate::TryIntoJs;
6use crate::JSValue;
7use crate::sys::napi_value;
8use crate::val::JsEnv;
9use crate::NjError;
10
11pub use num_bigint::*;
12
13impl<'a> JSValue<'a> for BigInt {
14 #[allow(clippy::not_unsafe_ptr_arg_deref)]
15 fn convert_to_rust(env: &'a JsEnv, js_value: napi_value) -> Result<Self, NjError> {
16 trace!("Converting JS BigInt to Rust!");
17
18 env.assert_type(js_value, crate::sys::napi_valuetype_napi_bigint)?;
19 let mut word_count = 0_usize;
20
21 crate::napi_call_result!(crate::sys::napi_get_value_bigint_words(
24 env.inner(),
25 js_value,
26 ptr::null_mut(),
27 &mut word_count,
28 ptr::null_mut(),
29 ))?;
30
31 let mut napi_buffer: Vec<u64> = vec![0; word_count];
33 let mut sign = 0;
34
35 crate::napi_call_result!(crate::sys::napi_get_value_bigint_words(
36 env.inner(),
37 js_value,
38 &mut sign,
39 &mut word_count,
40 napi_buffer.as_mut_ptr(),
41 ))?;
42
43 let mut bytes: Vec<u8> = Vec::new();
46 for i in &napi_buffer {
47 bytes.extend_from_slice(&i.to_le_bytes());
48 }
49
50 let sign = match sign {
52 0 => Sign::Plus,
53 1 => Sign::Minus,
54 _ => unreachable!(),
55 };
56 let res = BigInt::from_bytes_le(sign, &bytes);
57 trace!(
58 "Converted JS BigInt to Rust! words: {:#X?}, bytes: {:#?}, len: {:?}, bigint: {:#?}",
59 napi_buffer,
60 bytes,
61 bytes.len(),
62 res
63 );
64 Ok(res)
65 }
66}
67
68impl TryIntoJs for BigInt {
69 fn try_to_js(self, env: &JsEnv) -> Result<napi_value, NjError> {
70 let (sign, bytes) = self.to_bytes_le();
71 let mut words: Vec<u64> = Vec::new();
72 use std::cmp::min;
73
74 for i in 0..(bytes.len() / 8 + 1) {
76 let mut slice: [u8; 8] = [0; 8];
77
78 for (place, element) in slice
81 .iter_mut()
82 .zip(bytes[i * 8..min((i + 1) * 8, bytes.len())].iter())
83 {
84 *place = *element;
85 }
86 words.push(u64::from_le_bytes(slice));
87 }
88 let sign = match sign {
89 Sign::Minus => 1,
90 Sign::Plus | Sign::NoSign => 0,
91 };
92 let word_count = words.len();
93
94 trace!(
95 "Converted Rust BigInt to JS Bigint: {:#?}!, bytes: {:#?}, len: {:?}, words: {:#?}, word_count {:#?}, sign: {:#?}",
96 self,
97 bytes,
98 bytes.len(),
99 words,
100 word_count,
101 sign,
102 );
103
104 let mut napi_buffer = ptr::null_mut();
105
106 crate::napi_call_result!(crate::sys::napi_create_bigint_words(
108 env.inner(),
109 sign,
110 word_count,
111 words.as_ptr(),
112 &mut napi_buffer
113 ))?;
114 Ok(napi_buffer)
115 }
116}