-
Notifications
You must be signed in to change notification settings - Fork 286
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for bigint
#861
Support for bigint
#861
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,57 @@ | ||||||
use crate::napi::bindings as napi; | ||||||
use crate::raw::{Env, Local}; | ||||||
use std::mem::MaybeUninit; | ||||||
|
||||||
/// Create a new bigint object | ||||||
/// | ||||||
/// # Safety | ||||||
/// | ||||||
/// `env` is a raw pointer. Please ensure it points to a napi_env that is valid for the current context. | ||||||
pub unsafe fn new_bigint(env: Env, value: i64) -> Local { | ||||||
let mut local = MaybeUninit::zeroed(); | ||||||
let status = napi::create_bigint_int64(env, value, local.as_mut_ptr()); | ||||||
assert_eq!(status, napi::Status::Ok); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't checked to see if this can ever throw an exception--which is necessary for this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kjvalencik do you have some guidance on how to determine this? The napi docs for the function do not mention exceptions -- do I need to check the nodejs or v8 source code to determine this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately, it's not super clear. It's a manual task that's a combination of reading the Node/Node-API source and sometimes the JS spec. I expect that this can't ever fail except with bad data (which Rust type system protects against). |
||||||
local.assume_init() | ||||||
} | ||||||
|
||||||
/// Create a new bigint object | ||||||
/// | ||||||
/// # Safety | ||||||
/// | ||||||
/// `env` is a raw pointer. Please ensure it points to a napi_env that is valid for the current context. | ||||||
pub unsafe fn new_bigint_from_u64(env: Env, value: u64) -> Local { | ||||||
let mut local = MaybeUninit::zeroed(); | ||||||
let status = napi::create_bigint_uint64(env, value, local.as_mut_ptr()); | ||||||
assert_eq!(status, napi::Status::Ok); | ||||||
local.assume_init() | ||||||
} | ||||||
|
||||||
/// Get the value of a bigint object | ||||||
/// | ||||||
/// # Safety | ||||||
/// | ||||||
/// `env` is a raw pointer. Please ensure it points to a napi_env that is valid for the current context. | ||||||
/// `Local` must be an NAPI value associated with the given `Env` | ||||||
pub unsafe fn value_i64(env: Env, p: Local) -> (i64, bool) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you return a
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great idea 👍 |
||||||
let mut value: i64 = 0; | ||||||
let mut lossless = false; | ||||||
let status = | ||||||
napi::get_value_bigint_int64(env, p, &mut value as *mut _, &mut lossless as *mut _); | ||||||
assert_eq!(status, napi::Status::Ok); | ||||||
(value, lossless) | ||||||
} | ||||||
|
||||||
/// Get the value of a bigint object | ||||||
/// | ||||||
/// # Safety | ||||||
/// | ||||||
/// `env` is a raw pointer. Please ensure it points to a napi_env that is valid for the current context. | ||||||
/// `Local` must be an NAPI value associated with the given `Env` | ||||||
pub unsafe fn value_u64(env: Env, p: Local) -> (u64, bool) { | ||||||
let mut value: u64 = 0; | ||||||
let mut lossless = false; | ||||||
let status = | ||||||
napi::get_value_bigint_uint64(env, p, &mut value as *mut _, &mut lossless as *mut _); | ||||||
assert_eq!(status, napi::Status::Ok); | ||||||
(value, lossless) | ||||||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -336,6 +336,38 @@ mod napi6 { | |||||
) -> Status; | ||||||
|
||||||
fn get_instance_data(env: Env, data: *mut *mut c_void) -> Status; | ||||||
|
||||||
fn create_bigint_int64(env: Env, value: i64, result: *mut Value) -> Status; | ||||||
|
||||||
fn create_bigint_uint64(env: Env, value: u64, result: *mut Value) -> Status; | ||||||
|
||||||
fn create_bigint_words( | ||||||
env: Env, | ||||||
sign_bit: isize, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be a |
||||||
word_count: usize, | ||||||
words: *mut u64, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Also, cat ./target/debug/build/nodejs-sys-*/out/bindings.rs |
||||||
) -> Status; | ||||||
|
||||||
fn get_value_bigint_int64( | ||||||
env: Env, | ||||||
value: Value, | ||||||
result: *mut i64, | ||||||
lossless: *mut bool, | ||||||
) -> Status; | ||||||
|
||||||
fn get_value_bigint_uint64( | ||||||
env: Env, | ||||||
value: Value, | ||||||
result: *mut u64, | ||||||
lossless: *mut bool, | ||||||
) -> Status; | ||||||
|
||||||
fn get_value_bigint_words( | ||||||
env: Env, | ||||||
value: Value, | ||||||
sign_bit: *mut isize, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as previous comment, |
||||||
words: *mut u64, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing |
||||||
) -> Status; | ||||||
} | ||||||
); | ||||||
} | ||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,107 @@ | ||||||||||||||
use super::{private::ValueInternal, Value}; | ||||||||||||||
use crate::context::internal::Env; | ||||||||||||||
use crate::context::Context; | ||||||||||||||
use crate::handle::{internal::TransparentNoCopyWrapper, Handle, Managed}; | ||||||||||||||
use neon_runtime; | ||||||||||||||
use neon_runtime::raw; | ||||||||||||||
use std::fmt; | ||||||||||||||
use std::fmt::Debug; | ||||||||||||||
|
||||||||||||||
#[repr(C)] | ||||||||||||||
#[derive(Debug, Copy, Clone)] | ||||||||||||||
#[cfg_attr(docsrs, doc(cfg(feature = "napi-6")))] | ||||||||||||||
pub struct JsBigInt(raw::Local); | ||||||||||||||
|
||||||||||||||
impl Value for JsBigInt {} | ||||||||||||||
|
||||||||||||||
unsafe impl TransparentNoCopyWrapper for JsBigInt { | ||||||||||||||
type Inner = raw::Local; | ||||||||||||||
|
||||||||||||||
fn into_inner(self) -> Self::Inner { | ||||||||||||||
self.0 | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
impl Managed for JsBigInt { | ||||||||||||||
fn to_raw(&self) -> raw::Local { | ||||||||||||||
self.0 | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
fn from_raw(_: Env, h: raw::Local) -> Self { | ||||||||||||||
JsBigInt(h) | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
#[derive(Debug)] | ||||||||||||||
pub struct GetBigIntLossyValueResult<T> { | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's fairly common in Rust to put the data in the I think it would be more idiomatic to create an struct Error<T>(T);
impl<T> Error<T> {
fn into_inner(self) -> T {
self.0
}
}
impl<T> std::error::Error for Error {} |
||||||||||||||
pub value: T, | ||||||||||||||
/// Indicates whether the BigInt value was converted losslessly | ||||||||||||||
pub lossless: bool, | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
impl<T> fmt::Display for GetBigIntLossyValueResult<T> | ||||||||||||||
where | ||||||||||||||
T: fmt::Display, | ||||||||||||||
{ | ||||||||||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||||||||||||
write!(f, "{}", self.value) | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
impl Into<i64> for GetBigIntLossyValueResult<i64> { | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typically
Suggested change
|
||||||||||||||
fn into(self) -> i64 { | ||||||||||||||
self.value | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
impl Into<u64> for GetBigIntLossyValueResult<u64> { | ||||||||||||||
fn into(self) -> u64 { | ||||||||||||||
self.value | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
impl JsBigInt { | ||||||||||||||
pub fn new<'a, C: Context<'a>, T: Into<i64>>(cx: &mut C, x: T) -> Handle<'a, JsBigInt> { | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you think about making this generic over a trait? It could work well to allow providing an implementation for Nit, |
||||||||||||||
let env = cx.env().to_raw(); | ||||||||||||||
let value = x.into(); | ||||||||||||||
let local = unsafe { neon_runtime::bigint::new_bigint(env, value) }; | ||||||||||||||
let bigint = Handle::new_internal(JsBigInt(local)); | ||||||||||||||
bigint | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit let the type be returned directly instead of the unused variable binding.
Suggested change
|
||||||||||||||
} | ||||||||||||||
|
||||||||||||||
pub fn from_u64<'a, C: Context<'a>, T: Into<u64>>(cx: &mut C, x: T) -> Handle<'a, JsBigInt> { | ||||||||||||||
let env = cx.env().to_raw(); | ||||||||||||||
let value = x.into(); | ||||||||||||||
let local = unsafe { neon_runtime::bigint::new_bigint_from_u64(env, value) }; | ||||||||||||||
let bigint = Handle::new_internal(JsBigInt(local)); | ||||||||||||||
bigint | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
pub fn value_i64<'a, C: Context<'a>>(self, cx: &mut C) -> GetBigIntLossyValueResult<i64> { | ||||||||||||||
let env = cx.env().to_raw(); | ||||||||||||||
let result = unsafe { neon_runtime::bigint::value_i64(env, self.to_raw()) }; | ||||||||||||||
GetBigIntLossyValueResult { | ||||||||||||||
value: result.0, | ||||||||||||||
lossless: result.1, | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
pub fn value_u64<'a, C: Context<'a>>(self, cx: &mut C) -> GetBigIntLossyValueResult<u64> { | ||||||||||||||
let env = cx.env().to_raw(); | ||||||||||||||
let result = unsafe { neon_runtime::bigint::value_u64(env, self.to_raw()) }; | ||||||||||||||
GetBigIntLossyValueResult { | ||||||||||||||
value: result.0, | ||||||||||||||
lossless: result.1, | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
impl ValueInternal for JsBigInt { | ||||||||||||||
fn name() -> String { | ||||||||||||||
"bigint".to_string() | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Match the JavaScript capitalization.
Suggested change
|
||||||||||||||
} | ||||||||||||||
|
||||||||||||||
fn is_typeof<Other: Value>(env: Env, other: &Other) -> bool { | ||||||||||||||
unsafe { neon_runtime::tag::is_bigint(env.to_raw(), other.to_raw()) } | ||||||||||||||
} | ||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit, name this
new
since it's namespaced by thebigint
module.