napi/bindgen_runtime/js_values/
bigint.rs1use std::ptr;
12
13use crate::{check_status, sys};
14
15use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
16
17#[repr(transparent)]
19#[allow(non_camel_case_types)]
20pub struct i64n(pub i64);
21
22#[derive(Debug, Clone)]
25pub struct BigInt {
26 pub sign_bit: bool,
28 pub words: Vec<u64>,
29}
30
31impl TypeName for BigInt {
32 fn type_name() -> &'static str {
33 "BigInt"
34 }
35
36 fn value_type() -> crate::ValueType {
37 crate::ValueType::BigInt
38 }
39}
40
41impl ValidateNapiValue for BigInt {}
42
43impl FromNapiValue for BigInt {
44 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
45 let mut word_count = 0usize;
46 check_status!(unsafe {
47 sys::napi_get_value_bigint_words(
48 env,
49 napi_val,
50 ptr::null_mut(),
51 &mut word_count,
52 ptr::null_mut(),
53 )
54 })?;
55 let mut words: Vec<u64> = Vec::with_capacity(word_count);
56 let mut sign_bit = 0;
57
58 unsafe {
59 check_status!(sys::napi_get_value_bigint_words(
60 env,
61 napi_val,
62 &mut sign_bit,
63 &mut word_count,
64 words.as_mut_ptr(),
65 ))?;
66
67 words.set_len(word_count);
68 }
69 if word_count == 0 {
70 words = vec![0];
71 }
72 Ok(BigInt {
73 sign_bit: sign_bit == 1,
74 words,
75 })
76 }
77}
78
79impl BigInt {
80 pub fn get_u64(&self) -> (bool, u64, bool) {
85 (
86 self.sign_bit,
87 self.words[0],
88 !self.sign_bit && self.words.len() == 1,
89 )
90 }
91
92 pub fn get_i64(&self) -> (i64, bool) {
97 if self.sign_bit && self.words[0] == i64::MIN.unsigned_abs() {
98 return (i64::MIN, self.words.len() == 1);
99 }
100 (
101 self.words[0] as i64 * if self.sign_bit { -1 } else { 1 },
102 self.words.len() == 1 && self.words[0] as i64 >= 0,
103 )
104 }
105
106 pub fn get_i128(&self) -> (i128, bool) {
111 let len = self.words.len();
112 if len == 1 {
113 (
114 self.words[0] as i128 * if self.sign_bit { -1 } else { 1 },
115 true,
116 )
117 } else {
118 let val = self.words[0] as u128 + ((self.words[1] as u128) << 64);
119 if self.sign_bit && val == i128::MIN.unsigned_abs() {
120 return (i128::MIN, len > 2);
121 }
122 (
123 val as i128 * if self.sign_bit { -1 } else { 1 },
124 len == 2 && self.words[1] as i64 >= 0,
125 )
126 }
127 }
128
129 pub fn get_u128(&self) -> (bool, u128, bool) {
134 let len = self.words.len();
135 if len == 1 {
136 (self.sign_bit, self.words[0] as u128, true)
137 } else {
138 let val = self.words[0] as u128 + ((self.words[1] as u128) << 64);
139 (self.sign_bit, val, len == 2)
140 }
141 }
142}
143
144impl ToNapiValue for BigInt {
145 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
146 let mut raw_value = ptr::null_mut();
147 let len = val.words.len();
148 check_status!(unsafe {
149 sys::napi_create_bigint_words(
150 env,
151 match val.sign_bit {
152 true => 1,
153 false => 0,
154 },
155 len,
156 val.words.as_ptr(),
157 &mut raw_value,
158 )
159 })?;
160 Ok(raw_value)
161 }
162}
163
164pub(crate) unsafe fn u128_with_sign_to_napi_value(
165 env: sys::napi_env,
166 val: u128,
167 sign_bit: i32,
168) -> crate::Result<sys::napi_value> {
169 let mut raw_value = ptr::null_mut();
170 if cfg!(target_endian = "little") {
171 let words = &val as *const u128 as *const u64;
172 check_status!(
173 unsafe { sys::napi_create_bigint_words(env, sign_bit, 2, words, &mut raw_value) },
174 "Failed to create BigInt from u128"
175 )?;
176 return Ok(raw_value);
177 }
178
179 let arr: [u64; 2] = [val as _, (val >> 64) as _];
180 let words = &arr as *const u64;
181 check_status!(
182 unsafe { sys::napi_create_bigint_words(env, sign_bit, 2, words, &mut raw_value) },
183 "Failed to create BigInt from u128"
184 )?;
185 Ok(raw_value)
186}
187
188impl ToNapiValue for i128 {
189 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
190 let sign_bit = i32::from(val <= 0);
191 let val = val.unsigned_abs();
192 u128_with_sign_to_napi_value(env, val, sign_bit)
193 }
194}
195
196impl ToNapiValue for &i128 {
197 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
198 ToNapiValue::to_napi_value(env, *val)
199 }
200}
201
202impl ToNapiValue for &mut i128 {
203 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
204 ToNapiValue::to_napi_value(env, *val)
205 }
206}
207
208impl ToNapiValue for u128 {
209 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
210 u128_with_sign_to_napi_value(env, val, 0)
211 }
212}
213
214impl ToNapiValue for &u128 {
215 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
216 ToNapiValue::to_napi_value(env, *val)
217 }
218}
219
220impl ToNapiValue for &mut u128 {
221 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
222 ToNapiValue::to_napi_value(env, *val)
223 }
224}
225
226impl ToNapiValue for i64n {
227 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
228 let mut raw_value = ptr::null_mut();
229 check_status!(unsafe { sys::napi_create_bigint_int64(env, val.0, &mut raw_value) })?;
230 Ok(raw_value)
231 }
232}
233
234impl ToNapiValue for &i64n {
235 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
236 ToNapiValue::to_napi_value(env, i64n(val.0))
237 }
238}
239
240impl ToNapiValue for &mut i64n {
241 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
242 ToNapiValue::to_napi_value(env, i64n(val.0))
243 }
244}
245
246impl ToNapiValue for u64 {
247 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
248 let mut raw_value = ptr::null_mut();
249 check_status!(
250 unsafe { sys::napi_create_bigint_uint64(env, val, &mut raw_value) },
251 "Failed to create BigInt from u64"
252 )?;
253 Ok(raw_value)
254 }
255}
256
257impl ToNapiValue for &u64 {
258 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
259 ToNapiValue::to_napi_value(env, *val)
260 }
261}
262
263impl ToNapiValue for &mut u64 {
264 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
265 ToNapiValue::to_napi_value(env, *val)
266 }
267}
268
269impl ToNapiValue for usize {
270 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
271 let mut raw_value = ptr::null_mut();
272 check_status!(unsafe { sys::napi_create_bigint_uint64(env, val as u64, &mut raw_value) })?;
273 Ok(raw_value)
274 }
275}
276
277impl ToNapiValue for isize {
278 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
279 let mut raw_value = ptr::null_mut();
280 check_status!(unsafe { sys::napi_create_bigint_int64(env, val as i64, &mut raw_value) })?;
281 Ok(raw_value)
282 }
283}
284
285impl ToNapiValue for &usize {
286 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
287 ToNapiValue::to_napi_value(env, *val)
288 }
289}
290
291impl ToNapiValue for &mut usize {
292 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
293 ToNapiValue::to_napi_value(env, *val)
294 }
295}
296
297impl From<i64> for BigInt {
298 fn from(val: i64) -> Self {
299 BigInt {
300 sign_bit: val < 0,
301 words: vec![val.unsigned_abs()],
302 }
303 }
304}
305
306impl From<u64> for BigInt {
307 fn from(val: u64) -> Self {
308 BigInt {
309 sign_bit: false,
310 words: vec![val],
311 }
312 }
313}
314
315impl From<i128> for BigInt {
316 fn from(val: i128) -> Self {
317 let sign_bit = val < 0;
318 let val = val.unsigned_abs();
319 BigInt {
320 sign_bit,
321 words: vec![val as _, (val >> 64) as _],
322 }
323 }
324}
325
326impl From<u128> for BigInt {
327 fn from(val: u128) -> Self {
328 BigInt {
329 sign_bit: false,
330 words: vec![val as _, (val >> 64) as _],
331 }
332 }
333}