2020-07-10 20:14:32 +09:00
|
|
|
use std::convert::TryFrom;
|
|
|
|
use std::ptr;
|
|
|
|
|
2020-08-26 01:07:27 +09:00
|
|
|
use super::*;
|
2020-11-25 18:42:14 +09:00
|
|
|
use crate::{check_status, sys, Result};
|
2020-07-10 20:14:32 +09:00
|
|
|
|
2021-01-07 12:34:49 +09:00
|
|
|
#[derive(Clone, Copy)]
|
2020-08-26 01:07:27 +09:00
|
|
|
pub struct JsBigint {
|
|
|
|
pub(crate) raw: Value,
|
2020-12-02 19:39:20 +09:00
|
|
|
pub word_count: usize,
|
2020-08-26 01:07:27 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
impl JsBigint {
|
|
|
|
pub(crate) fn from_raw_unchecked(
|
|
|
|
env: sys::napi_env,
|
|
|
|
value: sys::napi_value,
|
2020-12-02 19:39:20 +09:00
|
|
|
word_count: usize,
|
2020-08-26 01:07:27 +09:00
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
raw: Value {
|
|
|
|
env,
|
|
|
|
value,
|
|
|
|
value_type: ValueType::Object,
|
|
|
|
},
|
|
|
|
word_count,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn into_unknown(self) -> Result<JsUnknown> {
|
2020-11-20 01:07:13 +09:00
|
|
|
unsafe { JsUnknown::from_raw(self.raw.env, self.raw.value) }
|
2020-08-26 01:07:27 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn coerce_to_number(self) -> Result<JsNumber> {
|
|
|
|
let mut new_raw_value = ptr::null_mut();
|
2020-11-25 18:42:14 +09:00
|
|
|
check_status!(unsafe {
|
2020-09-03 01:35:47 +09:00
|
|
|
sys::napi_coerce_to_number(self.raw.env, self.raw.value, &mut new_raw_value)
|
|
|
|
})?;
|
2020-08-26 01:07:27 +09:00
|
|
|
Ok(JsNumber(Value {
|
|
|
|
env: self.raw.env,
|
|
|
|
value: new_raw_value,
|
|
|
|
value_type: ValueType::Number,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn coerce_to_string(self) -> Result<JsString> {
|
|
|
|
let mut new_raw_value = ptr::null_mut();
|
2020-11-25 18:42:14 +09:00
|
|
|
check_status!(unsafe {
|
2020-09-03 01:35:47 +09:00
|
|
|
sys::napi_coerce_to_string(self.raw.env, self.raw.value, &mut new_raw_value)
|
|
|
|
})?;
|
2020-08-26 01:07:27 +09:00
|
|
|
Ok(JsString(Value {
|
|
|
|
env: self.raw.env,
|
|
|
|
value: new_raw_value,
|
|
|
|
value_type: ValueType::String,
|
|
|
|
}))
|
|
|
|
}
|
2021-09-23 02:29:09 +09:00
|
|
|
|
2020-08-26 01:07:27 +09:00
|
|
|
pub fn coerce_to_object(self) -> Result<JsObject> {
|
|
|
|
let mut new_raw_value = ptr::null_mut();
|
2020-11-25 18:42:14 +09:00
|
|
|
check_status!(unsafe {
|
2020-09-03 01:35:47 +09:00
|
|
|
sys::napi_coerce_to_object(self.raw.env, self.raw.value, &mut new_raw_value)
|
|
|
|
})?;
|
2020-08-26 01:07:27 +09:00
|
|
|
Ok(JsObject(Value {
|
|
|
|
env: self.raw.env,
|
|
|
|
value: new_raw_value,
|
|
|
|
value_type: ValueType::Object,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2020-11-10 12:09:25 +09:00
|
|
|
#[cfg(feature = "napi5")]
|
2020-08-26 01:07:27 +09:00
|
|
|
pub fn is_date(&self) -> Result<bool> {
|
|
|
|
let mut is_date = true;
|
2020-11-25 18:42:14 +09:00
|
|
|
check_status!(unsafe { sys::napi_is_date(self.raw.env, self.raw.value, &mut is_date) })?;
|
2020-08-26 01:07:27 +09:00
|
|
|
Ok(is_date)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_error(&self) -> Result<bool> {
|
|
|
|
let mut result = false;
|
2020-11-25 18:42:14 +09:00
|
|
|
check_status!(unsafe { sys::napi_is_error(self.raw.env, self.raw.value, &mut result) })?;
|
2020-08-26 01:07:27 +09:00
|
|
|
Ok(result)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_typedarray(&self) -> Result<bool> {
|
|
|
|
let mut result = false;
|
2020-11-25 18:42:14 +09:00
|
|
|
check_status!(unsafe { sys::napi_is_typedarray(self.raw.env, self.raw.value, &mut result) })?;
|
2020-08-26 01:07:27 +09:00
|
|
|
Ok(result)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_dataview(&self) -> Result<bool> {
|
|
|
|
let mut result = false;
|
2020-11-25 18:42:14 +09:00
|
|
|
check_status!(unsafe { sys::napi_is_dataview(self.raw.env, self.raw.value, &mut result) })?;
|
2020-08-26 01:07:27 +09:00
|
|
|
Ok(result)
|
|
|
|
}
|
|
|
|
|
2020-09-03 01:35:47 +09:00
|
|
|
pub fn is_array(&self) -> Result<bool> {
|
|
|
|
let mut is_array = false;
|
2020-11-25 18:42:14 +09:00
|
|
|
check_status!(unsafe { sys::napi_is_array(self.raw.env, self.raw.value, &mut is_array) })?;
|
2020-09-03 01:35:47 +09:00
|
|
|
Ok(is_array)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_buffer(&self) -> Result<bool> {
|
|
|
|
let mut is_buffer = false;
|
2020-11-25 18:42:14 +09:00
|
|
|
check_status!(unsafe { sys::napi_is_buffer(self.raw.env, self.raw.value, &mut is_buffer) })?;
|
2020-09-03 01:35:47 +09:00
|
|
|
Ok(is_buffer)
|
|
|
|
}
|
|
|
|
|
2021-05-17 18:29:38 +09:00
|
|
|
pub fn instanceof<Constructor: NapiRaw>(&self, constructor: Constructor) -> Result<bool> {
|
2020-08-26 01:07:27 +09:00
|
|
|
let mut result = false;
|
2020-11-25 18:42:14 +09:00
|
|
|
check_status!(unsafe {
|
2020-09-28 01:27:37 +09:00
|
|
|
sys::napi_instanceof(self.raw.env, self.raw.value, constructor.raw(), &mut result)
|
2020-08-26 01:07:27 +09:00
|
|
|
})?;
|
|
|
|
Ok(result)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-01 19:50:38 +09:00
|
|
|
impl NapiRaw for JsBigint {
|
|
|
|
unsafe fn raw(&self) -> sys::napi_value {
|
|
|
|
self.raw.value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'env> NapiRaw for &'env JsBigint {
|
2020-11-20 01:07:13 +09:00
|
|
|
unsafe fn raw(&self) -> sys::napi_value {
|
2020-08-26 01:07:27 +09:00
|
|
|
self.raw.value
|
|
|
|
}
|
2021-04-01 19:50:38 +09:00
|
|
|
}
|
2020-08-26 01:07:27 +09:00
|
|
|
|
2021-04-01 19:50:38 +09:00
|
|
|
impl NapiValue for JsBigint {
|
2020-11-20 01:07:13 +09:00
|
|
|
unsafe fn from_raw(env: sys::napi_env, value: sys::napi_value) -> Result<Self> {
|
2020-12-02 19:39:20 +09:00
|
|
|
let mut word_count = 0usize;
|
2020-11-25 18:42:14 +09:00
|
|
|
check_status!(sys::napi_get_value_bigint_words(
|
2020-11-20 01:07:13 +09:00
|
|
|
env,
|
|
|
|
value,
|
|
|
|
ptr::null_mut(),
|
2020-12-02 19:39:20 +09:00
|
|
|
&mut word_count,
|
2020-11-20 01:07:13 +09:00
|
|
|
ptr::null_mut(),
|
|
|
|
))?;
|
2020-08-26 01:07:27 +09:00
|
|
|
Ok(JsBigint {
|
|
|
|
raw: Value {
|
|
|
|
env,
|
|
|
|
value,
|
|
|
|
value_type: ValueType::Bigint,
|
|
|
|
},
|
|
|
|
word_count,
|
|
|
|
})
|
|
|
|
}
|
2020-09-07 18:26:28 +09:00
|
|
|
|
2020-11-20 01:07:13 +09:00
|
|
|
unsafe fn from_raw_unchecked(env: sys::napi_env, value: sys::napi_value) -> Self {
|
2020-12-02 19:39:20 +09:00
|
|
|
let mut word_count = 0usize;
|
2020-11-20 01:07:13 +09:00
|
|
|
let status = sys::napi_get_value_bigint_words(
|
|
|
|
env,
|
|
|
|
value,
|
|
|
|
ptr::null_mut(),
|
2020-12-02 19:39:20 +09:00
|
|
|
&mut word_count,
|
2020-11-20 01:07:13 +09:00
|
|
|
ptr::null_mut(),
|
|
|
|
);
|
2020-09-07 18:26:28 +09:00
|
|
|
debug_assert!(
|
|
|
|
Status::from(status) == Status::Ok,
|
|
|
|
"napi_get_value_bigint_words failed"
|
|
|
|
);
|
|
|
|
JsBigint {
|
|
|
|
raw: Value {
|
|
|
|
env,
|
|
|
|
value,
|
|
|
|
value_type: ValueType::Bigint,
|
|
|
|
},
|
|
|
|
word_count,
|
|
|
|
}
|
|
|
|
}
|
2020-08-26 01:07:27 +09:00
|
|
|
}
|
2020-07-10 20:14:32 +09:00
|
|
|
|
|
|
|
/// The BigInt will be converted losslessly when the value is over what an int64 could hold.
|
|
|
|
impl TryFrom<JsBigint> for i64 {
|
|
|
|
type Error = Error;
|
|
|
|
|
|
|
|
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 {
|
|
|
|
type Error = Error;
|
|
|
|
|
|
|
|
fn try_from(value: JsBigint) -> Result<u64> {
|
|
|
|
value.get_u64().map(|(v, _)| v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl JsBigint {
|
|
|
|
/// https://nodejs.org/api/n-api.html#n_api_napi_get_value_bigint_words
|
2020-08-26 01:07:27 +09:00
|
|
|
pub fn get_words(&mut self) -> Result<(bool, Vec<u64>)> {
|
|
|
|
let mut words: Vec<u64> = Vec::with_capacity(self.word_count as usize);
|
|
|
|
let word_count = &mut self.word_count;
|
|
|
|
let mut sign_bit = 0;
|
2020-11-25 18:42:14 +09:00
|
|
|
check_status!(unsafe {
|
2020-07-10 20:14:32 +09:00
|
|
|
sys::napi_get_value_bigint_words(
|
2020-08-26 01:07:27 +09:00
|
|
|
self.raw.env,
|
|
|
|
self.raw.value,
|
2020-07-10 20:14:32 +09:00
|
|
|
&mut sign_bit,
|
2020-12-02 19:39:20 +09:00
|
|
|
word_count,
|
2020-07-10 20:14:32 +09:00
|
|
|
words.as_mut_ptr(),
|
|
|
|
)
|
|
|
|
})?;
|
|
|
|
|
|
|
|
unsafe {
|
2020-08-26 01:07:27 +09:00
|
|
|
words.set_len(self.word_count as usize);
|
2020-07-10 20:14:32 +09:00
|
|
|
};
|
|
|
|
|
2020-08-26 01:07:27 +09:00
|
|
|
Ok((sign_bit == 1, words))
|
2020-07-10 20:14:32 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_u64(&self) -> Result<(u64, bool)> {
|
|
|
|
let mut val: u64 = 0;
|
|
|
|
let mut loss = false;
|
2020-11-25 18:42:14 +09:00
|
|
|
check_status!(unsafe {
|
2020-08-26 01:07:27 +09:00
|
|
|
sys::napi_get_value_bigint_uint64(self.raw.env, self.raw.value, &mut val, &mut loss)
|
2020-07-10 20:14:32 +09:00
|
|
|
})?;
|
|
|
|
|
|
|
|
Ok((val, loss))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_i64(&self) -> Result<(i64, bool)> {
|
|
|
|
let mut val: i64 = 0;
|
|
|
|
let mut loss: bool = false;
|
2020-11-25 18:42:14 +09:00
|
|
|
check_status!(unsafe {
|
2020-08-26 01:07:27 +09:00
|
|
|
sys::napi_get_value_bigint_int64(self.raw.env, self.raw.value, &mut val, &mut loss)
|
2020-07-10 20:14:32 +09:00
|
|
|
})?;
|
|
|
|
Ok((val, loss))
|
|
|
|
}
|
2020-08-26 01:07:27 +09:00
|
|
|
|
|
|
|
pub fn get_i128(&mut self) -> Result<(i128, bool)> {
|
|
|
|
let (signed, words) = self.get_words()?;
|
|
|
|
let len = words.len();
|
|
|
|
let i128_words: [i64; 2] = [words[0] as _, words[1] as _];
|
|
|
|
let mut val = unsafe { ptr::read(i128_words.as_ptr() as *const i128) };
|
|
|
|
if signed {
|
|
|
|
val = -val;
|
|
|
|
}
|
|
|
|
Ok((val, len > 2))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_u128(&mut self) -> Result<(bool, u128, bool)> {
|
|
|
|
let (signed, words) = self.get_words()?;
|
|
|
|
let len = words.len();
|
|
|
|
let u128_words: [u64; 2] = [words[0], words[1]];
|
|
|
|
let val = unsafe { ptr::read(u128_words.as_ptr() as *const u128) };
|
|
|
|
Ok((signed, val, len > 2))
|
|
|
|
}
|
2020-07-10 20:14:32 +09:00
|
|
|
}
|