Merge pull request #846 from napi-rs/bigint
feat(napi): BigInt codegen support
This commit is contained in:
commit
9a8484144c
18 changed files with 313 additions and 53 deletions
|
@ -241,9 +241,9 @@ yarn test
|
|||
| Result<()> | Error | 1 | v8.0.0 |
|
||||
| T: Fn(...) -> Result<T> | Function | 1 | v8.0.0 |
|
||||
| Async/Future | Promise<T> | 4 | v10.6.0 | async |
|
||||
| Task | Promise<T> | 1 | v8.5.0 |
|
||||
| AsyncTask | Promise<T> | 1 | v8.5.0 |
|
||||
| (NOT YET) | global | 1 | v8.0.0 |
|
||||
| (NOT YET) | Symbol | 1 | v8.0.0 |
|
||||
| JsSymbol | Symbol | 1 | v8.0.0 |
|
||||
| (NOT YET) | ArrayBuffer/TypedArray | 1 | v8.0.0 |
|
||||
| (NOT YET) | threadsafe function | 4 | v10.6.0 | napi4 |
|
||||
| (NOT YET) | BigInt | 6 | v10.7.0 | napi6 |
|
||||
| BigInt | BigInt | 6 | v10.7.0 | napi6 |
|
||||
|
|
|
@ -40,10 +40,12 @@ static KNOWN_TYPES: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
|
|||
("u16", "number"),
|
||||
("u32", "number"),
|
||||
("u64", "BigInt"),
|
||||
("i64n", "BigInt"),
|
||||
("u128", "BigInt"),
|
||||
("i128", "BigInt"),
|
||||
("usize", "BigInt"),
|
||||
("isize", "BigInt"),
|
||||
("JsBigInt", "BigInt"),
|
||||
("BigInt", "BigInt"),
|
||||
("bool", "boolean"),
|
||||
("String", "string"),
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
use crate::{check_status, sys, Error, JsUnknown, NapiRaw, NapiValue, Result, Status, ValueType};
|
||||
use std::ptr;
|
||||
|
||||
use crate::{check_status, sys, Error, JsUnknown, NapiRaw, NapiValue, Result, Status, ValueType};
|
||||
|
||||
mod array;
|
||||
#[cfg(feature = "napi6")]
|
||||
mod bigint;
|
||||
mod boolean;
|
||||
mod buffer;
|
||||
mod either;
|
||||
|
@ -15,6 +18,8 @@ mod string;
|
|||
mod task;
|
||||
|
||||
pub use array::*;
|
||||
#[cfg(feature = "napi6")]
|
||||
pub use bigint::*;
|
||||
pub use buffer::*;
|
||||
pub use either::*;
|
||||
pub use nil::*;
|
||||
|
|
211
crates/napi/src/bindgen_runtime/js_values/bigint.rs
Normal file
211
crates/napi/src/bindgen_runtime/js_values/bigint.rs
Normal file
|
@ -0,0 +1,211 @@
|
|||
/// We don't implement `FromNapiValue` for `i64` `u64` `i128` `u128` `isize` `usize` here
|
||||
/// Because converting directly from `JsBigInt` to these values may result in a loss of precision and thus unintended behavior
|
||||
/// ```rust
|
||||
/// use napi::{bindgen_prelude::*, JsBigint};
|
||||
///
|
||||
/// #[napi]
|
||||
/// fn bigint_add(mut a: Bigint, mut b: Bigint) -> u128 {
|
||||
/// a.get_u128().1 + b.get_u128().1 // We have opportunity to check if the `u128` has lost precision
|
||||
/// }
|
||||
/// ```
|
||||
use std::ptr;
|
||||
|
||||
use crate::{check_status, sys};
|
||||
|
||||
use super::{FromNapiValue, ToNapiValue, TypeName};
|
||||
|
||||
/// i64 is converted to `Number`
|
||||
#[repr(transparent)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct i64n(pub i64);
|
||||
|
||||
/// https://nodejs.org/api/n-api.html#napi_create_bigint_words
|
||||
/// The resulting BigInt is calculated as: (–1)^sign_bit (words[0] × (2^64)^0 + words[1] × (2^64)^1 + …)
|
||||
pub struct BigInt {
|
||||
/// true for negative numbers
|
||||
pub sign_bit: bool,
|
||||
pub words: Vec<u64>,
|
||||
}
|
||||
|
||||
impl TypeName for BigInt {
|
||||
fn type_name() -> &'static str {
|
||||
"BigInt"
|
||||
}
|
||||
|
||||
fn value_type() -> crate::ValueType {
|
||||
crate::ValueType::BigInt
|
||||
}
|
||||
}
|
||||
|
||||
impl FromNapiValue for BigInt {
|
||||
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
|
||||
let mut word_count = 0usize;
|
||||
check_status!(sys::napi_get_value_bigint_words(
|
||||
env,
|
||||
napi_val,
|
||||
ptr::null_mut(),
|
||||
&mut word_count,
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
let mut words: Vec<u64> = Vec::with_capacity(word_count as usize);
|
||||
let mut sign_bit = 0;
|
||||
check_status!(sys::napi_get_value_bigint_words(
|
||||
env,
|
||||
napi_val,
|
||||
&mut sign_bit,
|
||||
&mut word_count,
|
||||
words.as_mut_ptr(),
|
||||
))?;
|
||||
|
||||
words.set_len(word_count as usize);
|
||||
Ok(BigInt {
|
||||
sign_bit: sign_bit == 1,
|
||||
words,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl BigInt {
|
||||
/// (signed, value, lossless)
|
||||
/// get the first word of the BigInt as `u64`
|
||||
/// return true in the last element of tuple if the value is lossless
|
||||
/// or the value is truncated
|
||||
pub fn get_u64(&self) -> (bool, u64, bool) {
|
||||
(
|
||||
self.sign_bit,
|
||||
self.words[0],
|
||||
self.sign_bit && self.words.len() == 1,
|
||||
)
|
||||
}
|
||||
|
||||
/// (value, lossless)
|
||||
/// get the first word of the BigInt as `i64`
|
||||
/// return true if the value is lossless
|
||||
/// or the value is truncated
|
||||
pub fn get_i64(&self) -> (i64, bool) {
|
||||
let val = self.words[0] as i64;
|
||||
(val, val as u64 == self.words[0] && self.words.len() == 1)
|
||||
}
|
||||
|
||||
/// (value, lossless)
|
||||
/// get the first two words of the BigInt as `i128`
|
||||
/// return true if the value is lossless
|
||||
/// or the value is truncated
|
||||
pub fn get_i128(&self) -> (i128, bool) {
|
||||
let len = self.words.len();
|
||||
if len == 1 {
|
||||
(self.words[0] as i128, false)
|
||||
} else {
|
||||
let i128_words: [i64; 2] = [self.words[0] as _, self.words[1] as _];
|
||||
let mut val = unsafe { ptr::read(i128_words.as_ptr() as *const i128) };
|
||||
if self.sign_bit {
|
||||
val = -val;
|
||||
}
|
||||
(val, len > 2)
|
||||
}
|
||||
}
|
||||
|
||||
/// (signed, value, lossless)
|
||||
/// get the first two words of the BigInt as `u128`
|
||||
/// return true if the value is lossless
|
||||
/// or the value is truncated
|
||||
pub fn get_u128(&self) -> (bool, u128, bool) {
|
||||
let len = self.words.len();
|
||||
if len == 1 {
|
||||
(self.sign_bit, self.words[0] as u128, false)
|
||||
} else {
|
||||
let u128_words: [u64; 2] = [self.words[0], self.words[1]];
|
||||
let val = unsafe { ptr::read(u128_words.as_ptr() as *const u128) };
|
||||
(self.sign_bit, val, len > 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToNapiValue for BigInt {
|
||||
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
let len = val.words.len();
|
||||
check_status!(sys::napi_create_bigint_words(
|
||||
env,
|
||||
match val.sign_bit {
|
||||
true => 1,
|
||||
false => 0,
|
||||
},
|
||||
len,
|
||||
val.words.as_ptr(),
|
||||
&mut raw_value,
|
||||
))?;
|
||||
Ok(raw_value)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToNapiValue for i128 {
|
||||
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
let sign_bit = if val > 0 { 0 } else { 1 };
|
||||
let words = &val as *const i128 as *const u64;
|
||||
check_status!(sys::napi_create_bigint_words(
|
||||
env,
|
||||
sign_bit,
|
||||
2,
|
||||
words,
|
||||
&mut raw_value
|
||||
))?;
|
||||
Ok(raw_value)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToNapiValue for u128 {
|
||||
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
let words = &val as *const u128 as *const u64;
|
||||
check_status!(sys::napi_create_bigint_words(
|
||||
env,
|
||||
0,
|
||||
2,
|
||||
words,
|
||||
&mut raw_value
|
||||
))?;
|
||||
Ok(raw_value)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToNapiValue for i64n {
|
||||
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
check_status!(sys::napi_create_bigint_int64(env, val.0, &mut raw_value))?;
|
||||
Ok(raw_value)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToNapiValue for u64 {
|
||||
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
check_status!(sys::napi_create_bigint_uint64(env, val, &mut raw_value))?;
|
||||
Ok(raw_value)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToNapiValue for usize {
|
||||
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
check_status!(sys::napi_create_bigint_uint64(
|
||||
env,
|
||||
val as u64,
|
||||
&mut raw_value
|
||||
))?;
|
||||
Ok(raw_value)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToNapiValue for isize {
|
||||
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
check_status!(sys::napi_create_bigint_int64(
|
||||
env,
|
||||
val as i64,
|
||||
&mut raw_value
|
||||
))?;
|
||||
Ok(raw_value)
|
||||
}
|
||||
}
|
|
@ -56,7 +56,7 @@ impl FromNapiValue for Value {
|
|||
}
|
||||
}
|
||||
#[cfg(feature = "napi6")]
|
||||
ValueType::Bigint => todo!(),
|
||||
ValueType::BigInt => todo!(),
|
||||
_ => Value::Null,
|
||||
};
|
||||
|
||||
|
|
|
@ -100,43 +100,43 @@ impl Env {
|
|||
|
||||
/// [n_api_napi_create_bigint_int64](https://nodejs.org/api/n-api.html#n_api_napi_create_bigint_int64)
|
||||
#[cfg(feature = "napi6")]
|
||||
pub fn create_bigint_from_i64(&self, value: i64) -> Result<JsBigint> {
|
||||
pub fn create_bigint_from_i64(&self, value: i64) -> Result<JsBigInt> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
check_status!(unsafe { sys::napi_create_bigint_int64(self.0, value, &mut raw_value) })?;
|
||||
Ok(JsBigint::from_raw_unchecked(self.0, raw_value, 1))
|
||||
Ok(JsBigInt::from_raw_unchecked(self.0, raw_value, 1))
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi6")]
|
||||
pub fn create_bigint_from_u64(&self, value: u64) -> Result<JsBigint> {
|
||||
pub fn create_bigint_from_u64(&self, value: u64) -> Result<JsBigInt> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
check_status!(unsafe { sys::napi_create_bigint_uint64(self.0, value, &mut raw_value) })?;
|
||||
Ok(JsBigint::from_raw_unchecked(self.0, raw_value, 1))
|
||||
Ok(JsBigInt::from_raw_unchecked(self.0, raw_value, 1))
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi6")]
|
||||
pub fn create_bigint_from_i128(&self, value: i128) -> Result<JsBigint> {
|
||||
pub fn create_bigint_from_i128(&self, value: i128) -> Result<JsBigInt> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
let sign_bit = if value > 0 { 0 } else { 1 };
|
||||
let words = &value as *const i128 as *const u64;
|
||||
check_status!(unsafe {
|
||||
sys::napi_create_bigint_words(self.0, sign_bit, 2, words, &mut raw_value)
|
||||
})?;
|
||||
Ok(JsBigint::from_raw_unchecked(self.0, raw_value, 1))
|
||||
Ok(JsBigInt::from_raw_unchecked(self.0, raw_value, 1))
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi6")]
|
||||
pub fn create_bigint_from_u128(&self, value: u128) -> Result<JsBigint> {
|
||||
pub fn create_bigint_from_u128(&self, value: u128) -> Result<JsBigInt> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
let words = &value as *const u128 as *const u64;
|
||||
check_status!(unsafe { sys::napi_create_bigint_words(self.0, 0, 2, words, &mut raw_value) })?;
|
||||
Ok(JsBigint::from_raw_unchecked(self.0, raw_value, 1))
|
||||
Ok(JsBigInt::from_raw_unchecked(self.0, raw_value, 1))
|
||||
}
|
||||
|
||||
/// [n_api_napi_create_bigint_words](https://nodejs.org/api/n-api.html#n_api_napi_create_bigint_words)
|
||||
///
|
||||
/// The resulting BigInt will be negative when sign_bit is true.
|
||||
#[cfg(feature = "napi6")]
|
||||
pub fn create_bigint_from_words(&self, sign_bit: bool, words: Vec<u64>) -> Result<JsBigint> {
|
||||
pub fn create_bigint_from_words(&self, sign_bit: bool, words: Vec<u64>) -> Result<JsBigInt> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
let len = words.len();
|
||||
check_status!(unsafe {
|
||||
|
@ -151,7 +151,7 @@ impl Env {
|
|||
&mut raw_value,
|
||||
)
|
||||
})?;
|
||||
Ok(JsBigint::from_raw_unchecked(self.0, raw_value, len))
|
||||
Ok(JsBigInt::from_raw_unchecked(self.0, raw_value, len))
|
||||
}
|
||||
|
||||
pub fn create_string(&self, s: &str) -> Result<JsString> {
|
||||
|
|
|
@ -5,22 +5,22 @@ use super::*;
|
|||
use crate::{bindgen_runtime::TypeName, check_status, sys, Result};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct JsBigint {
|
||||
pub struct JsBigInt {
|
||||
pub(crate) raw: Value,
|
||||
pub word_count: usize,
|
||||
}
|
||||
|
||||
impl TypeName for JsBigint {
|
||||
impl TypeName for JsBigInt {
|
||||
fn type_name() -> &'static str {
|
||||
"BigInt"
|
||||
}
|
||||
|
||||
fn value_type() -> ValueType {
|
||||
ValueType::Bigint
|
||||
ValueType::BigInt
|
||||
}
|
||||
}
|
||||
|
||||
impl JsBigint {
|
||||
impl JsBigInt {
|
||||
pub(crate) fn from_raw_unchecked(
|
||||
env: sys::napi_env,
|
||||
value: sys::napi_value,
|
||||
|
@ -76,7 +76,6 @@ impl JsBigint {
|
|||
}))
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi5")]
|
||||
pub fn is_date(&self) -> Result<bool> {
|
||||
let mut is_date = true;
|
||||
check_status!(unsafe { sys::napi_is_date(self.raw.env, self.raw.value, &mut is_date) })?;
|
||||
|
@ -122,19 +121,19 @@ impl JsBigint {
|
|||
}
|
||||
}
|
||||
|
||||
impl NapiRaw for JsBigint {
|
||||
impl NapiRaw for JsBigInt {
|
||||
unsafe fn raw(&self) -> sys::napi_value {
|
||||
self.raw.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<'env> NapiRaw for &'env JsBigint {
|
||||
impl<'env> NapiRaw for &'env JsBigInt {
|
||||
unsafe fn raw(&self) -> sys::napi_value {
|
||||
self.raw.value
|
||||
}
|
||||
}
|
||||
|
||||
impl NapiValue for JsBigint {
|
||||
impl NapiValue for JsBigInt {
|
||||
unsafe fn from_raw(env: sys::napi_env, value: sys::napi_value) -> Result<Self> {
|
||||
let mut word_count = 0usize;
|
||||
check_status!(sys::napi_get_value_bigint_words(
|
||||
|
@ -144,11 +143,11 @@ impl NapiValue for JsBigint {
|
|||
&mut word_count,
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
Ok(JsBigint {
|
||||
Ok(JsBigInt {
|
||||
raw: Value {
|
||||
env,
|
||||
value,
|
||||
value_type: ValueType::Bigint,
|
||||
value_type: ValueType::BigInt,
|
||||
},
|
||||
word_count,
|
||||
})
|
||||
|
@ -167,11 +166,11 @@ impl NapiValue for JsBigint {
|
|||
Status::from(status) == Status::Ok,
|
||||
"napi_get_value_bigint_words failed"
|
||||
);
|
||||
JsBigint {
|
||||
JsBigInt {
|
||||
raw: Value {
|
||||
env,
|
||||
value,
|
||||
value_type: ValueType::Bigint,
|
||||
value_type: ValueType::BigInt,
|
||||
},
|
||||
word_count,
|
||||
}
|
||||
|
@ -179,24 +178,24 @@ impl NapiValue for JsBigint {
|
|||
}
|
||||
|
||||
/// The BigInt will be converted losslessly when the value is over what an int64 could hold.
|
||||
impl TryFrom<JsBigint> for i64 {
|
||||
impl TryFrom<JsBigInt> for i64 {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: JsBigint) -> Result<i64> {
|
||||
fn try_from(value: JsBigInt) -> Result<i64> {
|
||||
value.get_i64().map(|(v, _)| v)
|
||||
}
|
||||
}
|
||||
|
||||
/// The BigInt will be converted losslessly when the value is over what an uint64 could hold.
|
||||
impl TryFrom<JsBigint> for u64 {
|
||||
impl TryFrom<JsBigInt> for u64 {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: JsBigint) -> Result<u64> {
|
||||
fn try_from(value: JsBigInt) -> Result<u64> {
|
||||
value.get_u64().map(|(v, _)| v)
|
||||
}
|
||||
}
|
||||
|
||||
impl JsBigint {
|
||||
impl JsBigInt {
|
||||
/// https://nodejs.org/api/n-api.html#n_api_napi_get_value_bigint_words
|
||||
pub fn get_words(&mut self) -> Result<(bool, Vec<u64>)> {
|
||||
let mut words: Vec<u64> = Vec::with_capacity(self.word_count as usize);
|
||||
|
@ -221,21 +220,21 @@ impl JsBigint {
|
|||
|
||||
pub fn get_u64(&self) -> Result<(u64, bool)> {
|
||||
let mut val: u64 = 0;
|
||||
let mut loss = false;
|
||||
let mut lossless = false;
|
||||
check_status!(unsafe {
|
||||
sys::napi_get_value_bigint_uint64(self.raw.env, self.raw.value, &mut val, &mut loss)
|
||||
sys::napi_get_value_bigint_uint64(self.raw.env, self.raw.value, &mut val, &mut lossless)
|
||||
})?;
|
||||
|
||||
Ok((val, loss))
|
||||
Ok((val, lossless))
|
||||
}
|
||||
|
||||
pub fn get_i64(&self) -> Result<(i64, bool)> {
|
||||
let mut val: i64 = 0;
|
||||
let mut loss: bool = false;
|
||||
let mut lossless: bool = false;
|
||||
check_status!(unsafe {
|
||||
sys::napi_get_value_bigint_int64(self.raw.env, self.raw.value, &mut val, &mut loss)
|
||||
sys::napi_get_value_bigint_int64(self.raw.env, self.raw.value, &mut val, &mut lossless)
|
||||
})?;
|
||||
Ok((val, loss))
|
||||
Ok((val, lossless))
|
||||
}
|
||||
|
||||
pub fn get_i128(&mut self) -> Result<(i128, bool)> {
|
||||
|
|
|
@ -4,7 +4,7 @@ use serde::de::Visitor;
|
|||
use serde::de::{DeserializeSeed, EnumAccess, MapAccess, SeqAccess, Unexpected, VariantAccess};
|
||||
|
||||
#[cfg(feature = "napi6")]
|
||||
use crate::JsBigint;
|
||||
use crate::JsBigInt;
|
||||
use crate::{type_of, NapiValue, Value, ValueType};
|
||||
use crate::{
|
||||
Error, JsBoolean, JsBufferValue, JsNumber, JsObject, JsString, JsUnknown, Result, Status,
|
||||
|
@ -54,8 +54,8 @@ impl<'x, 'de, 'env> serde::de::Deserializer<'x> for &'de mut De<'env> {
|
|||
}
|
||||
}
|
||||
#[cfg(feature = "napi6")]
|
||||
ValueType::Bigint => {
|
||||
let mut js_bigint = unsafe { JsBigint::from_raw(self.0.env, self.0.value)? };
|
||||
ValueType::BigInt => {
|
||||
let mut js_bigint = unsafe { JsBigInt::from_raw(self.0.env, self.0.value)? };
|
||||
let (signed, v, _loss) = js_bigint.get_u128()?;
|
||||
if signed {
|
||||
visitor.visit_i128(-(v as i128))
|
||||
|
|
|
@ -33,7 +33,7 @@ mod value_ref;
|
|||
|
||||
pub use arraybuffer::*;
|
||||
#[cfg(feature = "napi6")]
|
||||
pub use bigint::JsBigint;
|
||||
pub use bigint::JsBigInt;
|
||||
pub use boolean::JsBoolean;
|
||||
pub use buffer::*;
|
||||
#[cfg(feature = "napi5")]
|
||||
|
|
|
@ -15,7 +15,7 @@ pub enum ValueType {
|
|||
Function = 7,
|
||||
External = 8,
|
||||
#[cfg(feature = "napi6")]
|
||||
Bigint = 9,
|
||||
BigInt = 9,
|
||||
Unknown = 1024,
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ impl From<i32> for ValueType {
|
|||
fn from(value: i32) -> ValueType {
|
||||
match value {
|
||||
#[cfg(feature = "napi6")]
|
||||
sys::ValueType::napi_bigint => ValueType::Bigint,
|
||||
sys::ValueType::napi_bigint => ValueType::BigInt,
|
||||
sys::ValueType::napi_boolean => ValueType::Boolean,
|
||||
sys::ValueType::napi_external => ValueType::External,
|
||||
sys::ValueType::napi_function => ValueType::Function,
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
use napi::{CallContext, JsBigint, JsNumber, JsObject, Result};
|
||||
use napi::{CallContext, JsBigInt, JsNumber, JsObject, Result};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[js_function]
|
||||
pub fn test_create_bigint_from_i64(ctx: CallContext) -> Result<JsBigint> {
|
||||
pub fn test_create_bigint_from_i64(ctx: CallContext) -> Result<JsBigInt> {
|
||||
ctx.env.create_bigint_from_i64(i64::max_value())
|
||||
}
|
||||
|
||||
#[js_function]
|
||||
pub fn test_create_bigint_from_u64(ctx: CallContext) -> Result<JsBigint> {
|
||||
pub fn test_create_bigint_from_u64(ctx: CallContext) -> Result<JsBigInt> {
|
||||
ctx.env.create_bigint_from_u64(u64::max_value())
|
||||
}
|
||||
|
||||
#[js_function]
|
||||
pub fn test_create_bigint_from_i128(ctx: CallContext) -> Result<JsBigint> {
|
||||
pub fn test_create_bigint_from_i128(ctx: CallContext) -> Result<JsBigInt> {
|
||||
ctx.env.create_bigint_from_i128(i128::max_value())
|
||||
}
|
||||
|
||||
#[js_function]
|
||||
pub fn test_create_bigint_from_u128(ctx: CallContext) -> Result<JsBigint> {
|
||||
pub fn test_create_bigint_from_u128(ctx: CallContext) -> Result<JsBigInt> {
|
||||
ctx.env.create_bigint_from_u128(u128::max_value())
|
||||
}
|
||||
|
||||
#[js_function]
|
||||
pub fn test_create_bigint_from_words(ctx: CallContext) -> Result<JsBigint> {
|
||||
pub fn test_create_bigint_from_words(ctx: CallContext) -> Result<JsBigInt> {
|
||||
ctx
|
||||
.env
|
||||
.create_bigint_from_words(true, vec![u64::max_value(), u64::max_value()])
|
||||
|
@ -30,14 +30,14 @@ pub fn test_create_bigint_from_words(ctx: CallContext) -> Result<JsBigint> {
|
|||
|
||||
#[js_function(1)]
|
||||
pub fn test_get_bigint_i64(ctx: CallContext) -> Result<JsNumber> {
|
||||
let js_bigint = ctx.get::<JsBigint>(0)?;
|
||||
let js_bigint = ctx.get::<JsBigInt>(0)?;
|
||||
let val = i64::try_from(js_bigint)?;
|
||||
ctx.env.create_int32(val as i32)
|
||||
}
|
||||
|
||||
#[js_function(1)]
|
||||
pub fn test_get_bigint_u64(ctx: CallContext) -> Result<JsNumber> {
|
||||
let js_bigint = ctx.get::<JsBigint>(0)?;
|
||||
let js_bigint = ctx.get::<JsBigInt>(0)?;
|
||||
let val = u64::try_from(js_bigint)?;
|
||||
ctx.env.create_int32(val as i32)
|
||||
}
|
||||
|
|
|
@ -13,6 +13,9 @@ Generated by [AVA](https://avajs.dev).
|
|||
export function sumNums(nums: Array<number>): number␊
|
||||
export function readFileAsync(path: string): Promise<Buffer>␊
|
||||
export function asyncMultiTwo(arg: number): Promise<number>␊
|
||||
export function bigintAdd(a: BigInt, b: BigInt): BigInt␊
|
||||
export function createBigInt(): BigInt␊
|
||||
export function createBigIntI64(): BigInt␊
|
||||
export function getCwd(callback: (arg0: string) => void): void␊
|
||||
export function readFile(callback: (arg0: Error | undefined, arg1: string | null) => void): void␊
|
||||
export function eitherStringOrNumber(input: string | number): number␊
|
||||
|
|
Binary file not shown.
|
@ -35,6 +35,9 @@ import {
|
|||
withoutAbortController,
|
||||
withAbortController,
|
||||
asyncMultiTwo,
|
||||
bigintAdd,
|
||||
createBigInt,
|
||||
createBigIntI64,
|
||||
} from '../'
|
||||
|
||||
test('number', (t) => {
|
||||
|
@ -217,3 +220,17 @@ MaybeTest('abort resolved task', async (t) => {
|
|||
await withAbortController(1, 2, ctrl.signal).then(() => ctrl.abort())
|
||||
t.pass('should not throw')
|
||||
})
|
||||
|
||||
const BigIntTest = typeof BigInt !== 'undefined' ? test : test.skip
|
||||
|
||||
BigIntTest('BigInt add', (t) => {
|
||||
t.is(bigintAdd(BigInt(1), BigInt(2)), BigInt(3))
|
||||
})
|
||||
|
||||
BigIntTest('create BigInt', (t) => {
|
||||
t.is(createBigInt(), BigInt('-3689348814741910323300'))
|
||||
})
|
||||
|
||||
BigIntTest('create BigInt i64', (t) => {
|
||||
t.is(createBigIntI64(), BigInt(100))
|
||||
})
|
||||
|
|
3
examples/napi/index.d.ts
vendored
3
examples/napi/index.d.ts
vendored
|
@ -3,6 +3,9 @@ export function getNums(): Array<number>
|
|||
export function sumNums(nums: Array<number>): number
|
||||
export function readFileAsync(path: string): Promise<Buffer>
|
||||
export function asyncMultiTwo(arg: number): Promise<number>
|
||||
export function bigintAdd(a: BigInt, b: BigInt): BigInt
|
||||
export function createBigInt(): BigInt
|
||||
export function createBigIntI64(): BigInt
|
||||
export function getCwd(callback: (arg0: string) => void): void
|
||||
export function readFile(callback: (arg0: Error | undefined, arg1: string | null) => void): void
|
||||
export function eitherStringOrNumber(input: string | number): number
|
||||
|
|
19
examples/napi/src/bigint.rs
Normal file
19
examples/napi/src/bigint.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
use napi::bindgen_prelude::*;
|
||||
|
||||
#[napi]
|
||||
fn bigint_add(a: BigInt, b: BigInt) -> u128 {
|
||||
a.get_u128().1 + b.get_u128().1
|
||||
}
|
||||
|
||||
#[napi]
|
||||
fn create_big_int() -> BigInt {
|
||||
BigInt {
|
||||
words: vec![100u64, 200u64],
|
||||
sign_bit: true,
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
fn create_big_int_i64() -> i64n {
|
||||
i64n(100)
|
||||
}
|
|
@ -5,6 +5,7 @@ extern crate serde_derive;
|
|||
|
||||
mod array;
|
||||
mod r#async;
|
||||
mod bigint;
|
||||
mod callback;
|
||||
mod class;
|
||||
mod class_factory;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "__test__",
|
||||
"target": "ES2015"
|
||||
"target": "ES2018"
|
||||
},
|
||||
"exclude": ["dist", "index.d.ts"]
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue