refactor(napi): create_buffer_with_borrowed_data now accepted raw ptr

This commit is contained in:
LongYinan 2020-12-24 11:53:23 +08:00
parent 9e73837635
commit 530359421c
No known key found for this signature in database
GPG key ID: A3FFE134A3E20881
3 changed files with 70 additions and 9 deletions

View file

@ -320,20 +320,19 @@ impl Env {
/// Provided `finalize_callback` will be called when `Buffer` got dropped. /// Provided `finalize_callback` will be called when `Buffer` got dropped.
pub unsafe fn create_buffer_with_borrowed_data<Hint, Finalize>( pub unsafe fn create_buffer_with_borrowed_data<Hint, Finalize>(
&self, &self,
data: &[u8], data: *const u8,
length: usize,
hint: Hint, hint: Hint,
finalize_callback: Option<Finalize>, finalize_callback: Option<Finalize>,
) -> Result<JsBufferValue> ) -> Result<JsBufferValue>
where where
Finalize: FnOnce(Env, Hint), Finalize: FnOnce(Hint, Env),
{ {
let length = data.len();
let mut raw_value = ptr::null_mut(); let mut raw_value = ptr::null_mut();
let data_ptr = data.as_ptr();
check_status!(sys::napi_create_external_buffer( check_status!(sys::napi_create_external_buffer(
self.0, self.0,
length, length,
data_ptr as *mut c_void, data as *mut c_void,
Some( Some(
raw_finalize_with_custom_callback::<Hint, Finalize> raw_finalize_with_custom_callback::<Hint, Finalize>
as unsafe extern "C" fn( as unsafe extern "C" fn(
@ -351,7 +350,7 @@ impl Env {
value: raw_value, value: raw_value,
value_type: ValueType::Object, value_type: ValueType::Object,
}), }),
mem::ManuallyDrop::new(Vec::from_raw_parts(data_ptr as *mut u8, length, length)), mem::ManuallyDrop::new(Vec::from_raw_parts(data as *mut u8, length, length)),
)) ))
} }
@ -1065,6 +1064,9 @@ impl Env {
} }
} }
/// This function could be used for `create_buffer_with_borrowed_data` and want do noting when Buffer finalized.
pub fn noop_finalize<Hint>(_hint: Hint, _env: Env) {}
unsafe extern "C" fn drop_buffer( unsafe extern "C" fn drop_buffer(
_env: sys::napi_env, _env: sys::napi_env,
finalize_data: *mut c_void, finalize_data: *mut c_void,
@ -1125,10 +1127,10 @@ unsafe extern "C" fn raw_finalize_with_custom_callback<Hint, Finalize>(
_finalize_data: *mut c_void, _finalize_data: *mut c_void,
finalize_hint: *mut c_void, finalize_hint: *mut c_void,
) where ) where
Finalize: FnOnce(Env, Hint), Finalize: FnOnce(Hint, Env),
{ {
let (hint, maybe_callback) = *Box::from_raw(finalize_hint as *mut (Hint, Option<Finalize>)); let (hint, maybe_callback) = *Box::from_raw(finalize_hint as *mut (Hint, Option<Finalize>));
if let Some(callback) = maybe_callback { if let Some(callback) = maybe_callback {
callback(Env::from_raw(env), hint); callback(hint, Env::from_raw(env));
}; };
} }

View file

@ -18,3 +18,17 @@ test('should copy', (t) => {
t.deepEqual(copyBuffer, fixture) t.deepEqual(copyBuffer, fixture)
t.not(fixture, copyBuffer) t.not(fixture, copyBuffer)
}) })
test('should create borrowed buffer with noop finalize', (t) => {
t.deepEqual(
bindings.createBorrowedBufferWithNoopFinalize(),
Buffer.from([1, 2, 3]),
)
})
test('should create borrowed buffer with finalize', (t) => {
t.deepEqual(
bindings.createBorrowedBufferWithFinalize(),
Buffer.from([1, 2, 3]),
)
})

View file

@ -1,6 +1,10 @@
use std::mem::ManuallyDrop;
use std::str; use std::str;
use napi::{CallContext, Error, JsBuffer, JsNumber, JsObject, JsString, Result, Status}; use napi::{
noop_finalize, CallContext, ContextlessResult, Env, Error, JsBuffer, JsNumber, JsObject,
JsString, Result, Status,
};
#[js_function(1)] #[js_function(1)]
pub fn get_buffer_length(ctx: CallContext) -> Result<JsNumber> { pub fn get_buffer_length(ctx: CallContext) -> Result<JsNumber> {
@ -22,9 +26,50 @@ pub fn copy_buffer(ctx: CallContext) -> Result<JsBuffer> {
ctx.env.create_buffer_copy(buffer).map(|b| b.into_raw()) ctx.env.create_buffer_copy(buffer).map(|b| b.into_raw())
} }
#[contextless_function]
pub fn create_borrowed_buffer_with_noop_finalize(env: Env) -> ContextlessResult<JsBuffer> {
let data = vec![1, 2, 3];
let data_ptr = data.as_ptr();
let length = data.len();
let manually_drop = ManuallyDrop::new(data);
unsafe {
env.create_buffer_with_borrowed_data(data_ptr, length, manually_drop, Some(noop_finalize))
}
.map(|b| Some(b.into_raw()))
}
#[contextless_function]
pub fn create_borrowed_buffer_with_finalize(env: Env) -> ContextlessResult<JsBuffer> {
let data = vec![1, 2, 3];
let data_ptr = data.as_ptr();
let length = data.len();
let manually_drop = ManuallyDrop::new(data);
unsafe {
env.create_buffer_with_borrowed_data(
data_ptr,
length,
manually_drop,
Some(|mut hint: ManuallyDrop<Vec<u8>>, _| {
ManuallyDrop::drop(&mut hint);
}),
)
}
.map(|b| Some(b.into_raw()))
}
pub fn register_js(exports: &mut JsObject) -> Result<()> { pub fn register_js(exports: &mut JsObject) -> Result<()> {
exports.create_named_method("getBufferLength", get_buffer_length)?; exports.create_named_method("getBufferLength", get_buffer_length)?;
exports.create_named_method("bufferToString", buffer_to_string)?; exports.create_named_method("bufferToString", buffer_to_string)?;
exports.create_named_method("copyBuffer", copy_buffer)?; exports.create_named_method("copyBuffer", copy_buffer)?;
exports.create_named_method(
"createBorrowedBufferWithNoopFinalize",
create_borrowed_buffer_with_noop_finalize,
)?;
exports.create_named_method(
"createBorrowedBufferWithFinalize",
create_borrowed_buffer_with_finalize,
)?;
Ok(()) Ok(())
} }