-
-
Notifications
You must be signed in to change notification settings - Fork 242
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(napi): implement external value
- Loading branch information
1 parent
d1a5f84
commit bdfb150
Showing
12 changed files
with
191 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
use std::any::TypeId; | ||
|
||
use crate::{check_status, Error, Status, TaggedObject}; | ||
|
||
use super::{FromNapiValue, ToNapiValue}; | ||
|
||
pub struct External<T: 'static> { | ||
obj: *mut TaggedObject<T>, | ||
size_hint: usize, | ||
pub adjusted_size: i64, | ||
} | ||
|
||
impl<T: 'static> External<T> { | ||
pub fn new(value: T) -> Self { | ||
Self { | ||
obj: Box::into_raw(Box::new(TaggedObject::new(value))), | ||
size_hint: 0, | ||
adjusted_size: 0, | ||
} | ||
} | ||
|
||
/// `size_hint` is a value to tell Node.js GC how much memory is used by this `External` object. | ||
/// | ||
/// If getting the exact `size_hint` is difficult, you can provide an approximate value, it's only effect to the GC. | ||
/// | ||
/// If your `External` object is not effect to GC, you can use `External::new` instead. | ||
pub fn new_with_size_hint(value: T, size_hint: usize) -> Self { | ||
Self { | ||
obj: Box::into_raw(Box::new(TaggedObject::new(value))), | ||
size_hint, | ||
adjusted_size: 0, | ||
} | ||
} | ||
} | ||
|
||
impl<T: 'static> FromNapiValue for External<T> { | ||
unsafe fn from_napi_value( | ||
env: napi_sys::napi_env, | ||
napi_val: napi_sys::napi_value, | ||
) -> crate::Result<Self> { | ||
let mut unknown_tagged_object = std::ptr::null_mut(); | ||
check_status!( | ||
napi_sys::napi_get_value_external(env, napi_val, &mut unknown_tagged_object), | ||
"Failed to get external value" | ||
)?; | ||
|
||
let type_id = unknown_tagged_object as *const TypeId; | ||
if *type_id == TypeId::of::<T>() { | ||
let tagged_object = unknown_tagged_object as *mut TaggedObject<T>; | ||
Ok(Self { | ||
obj: tagged_object, | ||
size_hint: 0, | ||
adjusted_size: 0, | ||
}) | ||
} else { | ||
Err(Error::new( | ||
Status::InvalidArg, | ||
"T on `get_value_external` is not the type of wrapped object".to_owned(), | ||
)) | ||
} | ||
} | ||
} | ||
|
||
impl<T: 'static> AsRef<T> for External<T> { | ||
fn as_ref(&self) -> &T { | ||
unsafe { Box::leak(Box::from_raw(self.obj)).object.as_ref().unwrap() } | ||
} | ||
} | ||
|
||
impl<T: 'static> AsMut<T> for External<T> { | ||
fn as_mut(&mut self) -> &mut T { | ||
unsafe { Box::leak(Box::from_raw(self.obj)).object.as_mut().unwrap() } | ||
} | ||
} | ||
|
||
impl<T: 'static> ToNapiValue for External<T> { | ||
unsafe fn to_napi_value( | ||
env: napi_sys::napi_env, | ||
mut val: Self, | ||
) -> crate::Result<napi_sys::napi_value> { | ||
let mut napi_value = std::ptr::null_mut(); | ||
check_status!( | ||
napi_sys::napi_create_external( | ||
env, | ||
val.obj as *mut _, | ||
Some(crate::raw_finalize::<T>), | ||
Box::into_raw(Box::new(Some(val.size_hint as i64))) as *mut _, | ||
&mut napi_value | ||
), | ||
"Create external value failed" | ||
)?; | ||
|
||
let mut adjusted_external_memory_size = std::mem::MaybeUninit::new(0); | ||
|
||
if val.size_hint != 0 { | ||
check_status!( | ||
napi_sys::napi_adjust_external_memory( | ||
env, | ||
val.size_hint as i64, | ||
adjusted_external_memory_size.as_mut_ptr() | ||
), | ||
"Adjust external memory failed" | ||
)?; | ||
}; | ||
|
||
val.adjusted_size = adjusted_external_memory_size.assume_init(); | ||
|
||
Ok(napi_value) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
use napi::bindgen_prelude::*; | ||
|
||
#[napi] | ||
pub fn create_external(size: u32) -> External<u32> { | ||
External::new(size) | ||
} | ||
|
||
#[napi] | ||
pub fn create_external_string(content: String) -> External<String> { | ||
External::new(content) | ||
} | ||
|
||
#[napi] | ||
pub fn get_external(external: External<u32>) -> u32 { | ||
*external.as_ref() | ||
} | ||
|
||
#[napi] | ||
pub fn mutate_external(mut external: External<u32>, new_val: u32) { | ||
*external.as_mut() = new_val; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters