mirror of
https://github.com/napi-rs/napi-rs.git
synced 2025-12-08 19:56:07 +00:00
feat(napi): serialize BigInt to serde::Value (#2659)
This commit is contained in:
parent
abf041542c
commit
f8fab45de7
@ -169,15 +169,19 @@ pub(crate) unsafe fn u128_with_sign_to_napi_value(
|
||||
let mut raw_value = ptr::null_mut();
|
||||
if cfg!(target_endian = "little") {
|
||||
let words = &val as *const u128 as *const u64;
|
||||
check_status!(unsafe {
|
||||
sys::napi_create_bigint_words(env, sign_bit, 2, words, &mut raw_value)
|
||||
})?;
|
||||
check_status!(
|
||||
unsafe { sys::napi_create_bigint_words(env, sign_bit, 2, words, &mut raw_value) },
|
||||
"Failed to create BigInt from u128"
|
||||
)?;
|
||||
return Ok(raw_value);
|
||||
}
|
||||
|
||||
let arr: [u64; 2] = [val as _, (val >> 64) as _];
|
||||
let words = &arr as *const u64;
|
||||
check_status!(unsafe { sys::napi_create_bigint_words(env, sign_bit, 2, words, &mut raw_value) })?;
|
||||
check_status!(
|
||||
unsafe { sys::napi_create_bigint_words(env, sign_bit, 2, words, &mut raw_value) },
|
||||
"Failed to create BigInt from u128"
|
||||
)?;
|
||||
Ok(raw_value)
|
||||
}
|
||||
|
||||
@ -242,7 +246,10 @@ impl ToNapiValue for &mut i64n {
|
||||
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!(unsafe { sys::napi_create_bigint_uint64(env, val, &mut raw_value) })?;
|
||||
check_status!(
|
||||
unsafe { sys::napi_create_bigint_uint64(env, val, &mut raw_value) },
|
||||
"Failed to create BigInt from u64"
|
||||
)?;
|
||||
Ok(raw_value)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr;
|
||||
|
||||
use serde_json::{Map, Number, Value};
|
||||
|
||||
@ -51,7 +52,25 @@ impl FromNapiValue for Value {
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "napi6")]
|
||||
ValueType::BigInt => todo!(),
|
||||
ValueType::BigInt => {
|
||||
let n = unsafe { BigInt::from_napi_value(env, napi_val)? };
|
||||
// negative
|
||||
if n.sign_bit {
|
||||
let (v, lossless) = n.get_i64();
|
||||
if lossless {
|
||||
Value::Number(v.into())
|
||||
} else {
|
||||
Value::String(to_string(env, napi_val)?)
|
||||
}
|
||||
} else {
|
||||
let (_, v, lossless) = n.get_u64();
|
||||
if lossless {
|
||||
Value::Number(v.into())
|
||||
} else {
|
||||
Value::String(to_string(env, napi_val)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
ValueType::Null => Value::Null,
|
||||
ValueType::Function => {
|
||||
return Err(Error::new(
|
||||
@ -89,6 +108,13 @@ impl FromNapiValue for Value {
|
||||
}
|
||||
}
|
||||
|
||||
fn to_string(env: sys::napi_env, napi_val: sys::napi_value) -> Result<String> {
|
||||
let mut string = ptr::null_mut();
|
||||
check_status!(unsafe { sys::napi_coerce_to_string(env, napi_val, &mut string) })?;
|
||||
let s = unsafe { String::from_napi_value(env, string) }?;
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
impl ToNapiValue for &Map<String, Value> {
|
||||
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
|
||||
let mut obj = Object::new(&Env::from(env))?;
|
||||
|
||||
@ -572,6 +572,8 @@ Generated by [AVA](https://avajs.dev).
|
||||
␊
|
||||
export declare function generateFunctionAndCallIt(): FunctionData␊
|
||||
␊
|
||||
export declare function getBigintJsonValue(value: bigint): void␊
|
||||
␊
|
||||
export declare function getBtreeMapping(): Record<string, number>␊
|
||||
␊
|
||||
export declare function getBuffer(): Buffer␊
|
||||
|
||||
Binary file not shown.
@ -137,6 +137,7 @@ import {
|
||||
testSerdeRoundtrip,
|
||||
testSerdeBigNumberPrecision,
|
||||
testSerdeBufferBytes,
|
||||
getBigintJsonValue,
|
||||
createObjWithProperty,
|
||||
receiveObjectOnlyFromJs,
|
||||
dateToNumber,
|
||||
@ -883,6 +884,14 @@ test('serde-buffer-bytes', (t) => {
|
||||
t.is(testSerdeBufferBytes({ code: new ArrayBuffer(0) }), 0n)
|
||||
})
|
||||
|
||||
test('get bigint json value', (t) => {
|
||||
t.notThrows(() => {
|
||||
getBigintJsonValue(-1n)
|
||||
getBigintJsonValue(1n)
|
||||
getBigintJsonValue(18446744073709551620n)
|
||||
})
|
||||
})
|
||||
|
||||
test('buffer', (t) => {
|
||||
let buf = getBuffer()
|
||||
t.is(buf.toString('utf-8'), 'Hello world')
|
||||
|
||||
@ -210,6 +210,7 @@ export const f64ArrayToArray = __napiModule.exports.f64ArrayToArray
|
||||
export const fibonacci = __napiModule.exports.fibonacci
|
||||
export const fnReceivedAliased = __napiModule.exports.fnReceivedAliased
|
||||
export const generateFunctionAndCallIt = __napiModule.exports.generateFunctionAndCallIt
|
||||
export const getBigintJsonValue = __napiModule.exports.getBigintJsonValue
|
||||
export const getBtreeMapping = __napiModule.exports.getBtreeMapping
|
||||
export const getBuffer = __napiModule.exports.getBuffer
|
||||
export const getBufferSlice = __napiModule.exports.getBufferSlice
|
||||
|
||||
@ -234,6 +234,7 @@ module.exports.f64ArrayToArray = __napiModule.exports.f64ArrayToArray
|
||||
module.exports.fibonacci = __napiModule.exports.fibonacci
|
||||
module.exports.fnReceivedAliased = __napiModule.exports.fnReceivedAliased
|
||||
module.exports.generateFunctionAndCallIt = __napiModule.exports.generateFunctionAndCallIt
|
||||
module.exports.getBigintJsonValue = __napiModule.exports.getBigintJsonValue
|
||||
module.exports.getBtreeMapping = __napiModule.exports.getBtreeMapping
|
||||
module.exports.getBuffer = __napiModule.exports.getBuffer
|
||||
module.exports.getBufferSlice = __napiModule.exports.getBufferSlice
|
||||
|
||||
@ -524,6 +524,7 @@ module.exports.f64ArrayToArray = nativeBinding.f64ArrayToArray
|
||||
module.exports.fibonacci = nativeBinding.fibonacci
|
||||
module.exports.fnReceivedAliased = nativeBinding.fnReceivedAliased
|
||||
module.exports.generateFunctionAndCallIt = nativeBinding.generateFunctionAndCallIt
|
||||
module.exports.getBigintJsonValue = nativeBinding.getBigintJsonValue
|
||||
module.exports.getBtreeMapping = nativeBinding.getBtreeMapping
|
||||
module.exports.getBuffer = nativeBinding.getBuffer
|
||||
module.exports.getBufferSlice = nativeBinding.getBufferSlice
|
||||
|
||||
@ -534,6 +534,8 @@ export interface FunctionData {
|
||||
|
||||
export declare function generateFunctionAndCallIt(): FunctionData
|
||||
|
||||
export declare function getBigintJsonValue(value: bigint): void
|
||||
|
||||
export declare function getBtreeMapping(): Record<string, number>
|
||||
|
||||
export declare function getBuffer(): Buffer
|
||||
|
||||
@ -69,3 +69,27 @@ impl PackageJsonReader {
|
||||
&self.i
|
||||
}
|
||||
}
|
||||
|
||||
#[napi(catch_unwind, ts_args_type = "value: bigint")]
|
||||
pub fn get_bigint_json_value(bigint_json_value: Value) {
|
||||
match bigint_json_value {
|
||||
Value::Number(n) => {
|
||||
if let Some(u) = n.as_u64() {
|
||||
assert_eq!(u, 1);
|
||||
return;
|
||||
}
|
||||
if let Some(i) = n.as_i64() {
|
||||
assert_eq!(i, -1);
|
||||
return;
|
||||
}
|
||||
unreachable!("should not happen");
|
||||
}
|
||||
Value::String(s) => {
|
||||
assert_eq!(s, "18446744073709551620");
|
||||
return;
|
||||
}
|
||||
_ => {
|
||||
unreachable!("should not happen");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user