napi/bindgen_runtime/js_values/
bigint.rs1use std::{cmp::max, 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, Eq)]
25pub struct BigInt {
26 pub sign_bit: bool,
28 pub words: Vec<u64>,
29}
30
31impl PartialEq for BigInt {
32 fn eq(&self, other: &Self) -> bool {
33 for i in 0..max(self.words.len(), other.words.len()) {
34 if self.words.get(i).unwrap_or(&0) != other.words.get(i).unwrap_or(&0) {
35 return false;
36 }
37 }
38 self.sign_bit == other.sign_bit
39 }
40}
41
42impl TypeName for BigInt {
43 fn type_name() -> &'static str {
44 "BigInt"
45 }
46
47 fn value_type() -> crate::ValueType {
48 crate::ValueType::BigInt
49 }
50}
51
52impl ValidateNapiValue for BigInt {}
53
54impl FromNapiValue for BigInt {
55 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
56 let mut word_count = 0usize;
57 check_status!(unsafe {
58 sys::napi_get_value_bigint_words(
59 env,
60 napi_val,
61 ptr::null_mut(),
62 &mut word_count,
63 ptr::null_mut(),
64 )
65 })?;
66 let mut words: Vec<u64> = Vec::with_capacity(word_count);
67 let mut sign_bit = 0;
68
69 unsafe {
70 check_status!(sys::napi_get_value_bigint_words(
71 env,
72 napi_val,
73 &mut sign_bit,
74 &mut word_count,
75 words.as_mut_ptr(),
76 ))?;
77
78 words.set_len(word_count);
79 }
80 if word_count == 0 {
81 words = vec![0];
82 }
83 Ok(BigInt {
84 sign_bit: sign_bit == 1,
85 words,
86 })
87 }
88}
89
90impl BigInt {
91 pub fn get_u64(&self) -> (bool, u64, bool) {
96 (
97 self.sign_bit,
98 self.words[0],
99 !self.sign_bit && self.words.len() == 1,
100 )
101 }
102
103 pub fn get_i64(&self) -> (i64, bool) {
108 if self.sign_bit && self.words[0] == i64::MIN.unsigned_abs() {
109 return (i64::MIN, self.words.len() == 1);
110 }
111 (
112 self.words[0] as i64 * if self.sign_bit { -1 } else { 1 },
113 self.words.len() == 1 && self.words[0] as i64 >= 0,
114 )
115 }
116
117 pub fn get_i128(&self) -> (i128, bool) {
122 let len = self.words.len();
123 if len == 1 {
124 (
125 self.words[0] as i128 * if self.sign_bit { -1 } else { 1 },
126 true,
127 )
128 } else {
129 let val = self.words[0] as u128 + ((self.words[1] as u128) << 64);
130 if self.sign_bit && val == i128::MIN.unsigned_abs() {
131 return (i128::MIN, len > 2);
132 }
133 (
134 val as i128 * if self.sign_bit { -1 } else { 1 },
135 len == 2 && self.words[1] as i64 >= 0,
136 )
137 }
138 }
139
140 pub fn get_u128(&self) -> (bool, u128, bool) {
145 let len = self.words.len();
146 if len == 1 {
147 (self.sign_bit, self.words[0] as u128, true)
148 } else {
149 let val = self.words[0] as u128 + ((self.words[1] as u128) << 64);
150 (self.sign_bit, val, len == 2)
151 }
152 }
153}
154
155impl ToNapiValue for BigInt {
156 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
157 let mut raw_value = ptr::null_mut();
158 let len = val.words.len();
159 check_status!(unsafe {
160 sys::napi_create_bigint_words(
161 env,
162 match val.sign_bit {
163 true => 1,
164 false => 0,
165 },
166 len,
167 val.words.as_ptr(),
168 &mut raw_value,
169 )
170 })?;
171 Ok(raw_value)
172 }
173}
174
175pub(crate) unsafe fn u128_with_sign_to_napi_value(
176 env: sys::napi_env,
177 val: u128,
178 sign_bit: i32,
179) -> crate::Result<sys::napi_value> {
180 let mut raw_value = ptr::null_mut();
181 if cfg!(target_endian = "little") {
182 let words = &val as *const u128 as *const u64;
183 check_status!(
184 unsafe { sys::napi_create_bigint_words(env, sign_bit, 2, words, &mut raw_value) },
185 "Failed to create BigInt from u128"
186 )?;
187 return Ok(raw_value);
188 }
189
190 let arr: [u64; 2] = [val as _, (val >> 64) as _];
191 let words = &arr as *const u64;
192 check_status!(
193 unsafe { sys::napi_create_bigint_words(env, sign_bit, 2, words, &mut raw_value) },
194 "Failed to create BigInt from u128"
195 )?;
196 Ok(raw_value)
197}
198
199impl ToNapiValue for i128 {
200 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
201 let sign_bit = i32::from(val <= 0);
202 let val = val.unsigned_abs();
203 u128_with_sign_to_napi_value(env, val, sign_bit)
204 }
205}
206
207impl ToNapiValue for &i128 {
208 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
209 ToNapiValue::to_napi_value(env, *val)
210 }
211}
212
213impl ToNapiValue for &mut i128 {
214 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
215 ToNapiValue::to_napi_value(env, *val)
216 }
217}
218
219impl ToNapiValue for u128 {
220 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
221 u128_with_sign_to_napi_value(env, val, 0)
222 }
223}
224
225impl ToNapiValue for &u128 {
226 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
227 ToNapiValue::to_napi_value(env, *val)
228 }
229}
230
231impl ToNapiValue for &mut u128 {
232 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
233 ToNapiValue::to_napi_value(env, *val)
234 }
235}
236
237impl ToNapiValue for i64n {
238 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
239 let mut raw_value = ptr::null_mut();
240 check_status!(unsafe { sys::napi_create_bigint_int64(env, val.0, &mut raw_value) })?;
241 Ok(raw_value)
242 }
243}
244
245impl ToNapiValue for &i64n {
246 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
247 ToNapiValue::to_napi_value(env, i64n(val.0))
248 }
249}
250
251impl ToNapiValue for &mut i64n {
252 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
253 ToNapiValue::to_napi_value(env, i64n(val.0))
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 let mut raw_value = ptr::null_mut();
260 check_status!(
261 unsafe { sys::napi_create_bigint_uint64(env, val, &mut raw_value) },
262 "Failed to create BigInt from u64"
263 )?;
264 Ok(raw_value)
265 }
266}
267
268impl ToNapiValue for &u64 {
269 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
270 ToNapiValue::to_napi_value(env, *val)
271 }
272}
273
274impl ToNapiValue for &mut u64 {
275 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
276 ToNapiValue::to_napi_value(env, *val)
277 }
278}
279
280impl ToNapiValue for usize {
281 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
282 let mut raw_value = ptr::null_mut();
283 check_status!(unsafe { sys::napi_create_bigint_uint64(env, val as u64, &mut raw_value) })?;
284 Ok(raw_value)
285 }
286}
287
288impl ToNapiValue for isize {
289 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
290 let mut raw_value = ptr::null_mut();
291 check_status!(unsafe { sys::napi_create_bigint_int64(env, val as i64, &mut raw_value) })?;
292 Ok(raw_value)
293 }
294}
295
296impl ToNapiValue for &usize {
297 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
298 ToNapiValue::to_napi_value(env, *val)
299 }
300}
301
302impl ToNapiValue for &mut usize {
303 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
304 ToNapiValue::to_napi_value(env, *val)
305 }
306}
307
308impl From<i64> for BigInt {
309 fn from(val: i64) -> Self {
310 BigInt {
311 sign_bit: val < 0,
312 words: vec![val.unsigned_abs()],
313 }
314 }
315}
316
317impl From<u64> for BigInt {
318 fn from(val: u64) -> Self {
319 BigInt {
320 sign_bit: false,
321 words: vec![val],
322 }
323 }
324}
325
326impl From<i128> for BigInt {
327 fn from(val: i128) -> Self {
328 let sign_bit = val < 0;
329 let val = val.unsigned_abs();
330 BigInt {
331 sign_bit,
332 words: vec![val as _, (val >> 64) as _],
333 }
334 }
335}
336
337impl From<u128> for BigInt {
338 fn from(val: u128) -> Self {
339 BigInt {
340 sign_bit: false,
341 words: vec![val as _, (val >> 64) as _],
342 }
343 }
344}
345
346#[test]
347fn test_bigint_comparison() {
348 assert_eq!(BigInt::from(1_i64), BigInt::from(1_i64));
349 assert_eq!(BigInt::from(1_i64), BigInt::from(1_i128));
350 assert_eq!(BigInt::from(1_i64), BigInt::from(1_u128));
351 assert_eq!(BigInt::from(1_i64), BigInt::from(1_u64));
352
353 assert_eq!(BigInt::from(-1_i64), BigInt::from(-1_i128));
354
355 assert_ne!(BigInt::from(1_i64), BigInt::from(-1_i128));
356 assert_ne!(BigInt::from(1_i64), BigInt::from(2_i64));
357
358 assert_eq!(BigInt::from(i128::MAX), BigInt::from(i128::MAX));
359 assert_ne!(BigInt::from(i64::MAX), BigInt::from(i128::MAX));
360}