From 911a0c139d6862b2042b80439e958e2d0a9257fc Mon Sep 17 00:00:00 2001 From: LongYinan Date: Tue, 5 Jan 2021 23:27:01 +0800 Subject: [PATCH] feat(napi): Env::create_arraybuffer_with_borrowed_data --- napi/src/env.rs | 47 +++++++++++++++++++++++++++++-- napi/src/js_values/arraybuffer.rs | 36 +++++++++++++++++------ napi/src/js_values/mod.rs | 3 +- 3 files changed, 73 insertions(+), 13 deletions(-) diff --git a/napi/src/env.rs b/napi/src/env.rs index 73a294d2..e5894997 100644 --- a/napi/src/env.rs +++ b/napi/src/env.rs @@ -410,7 +410,7 @@ impl Env { Ok(JsArrayBufferValue::new( unsafe { JsArrayBuffer::from_raw_unchecked(self.0, raw_value) }, - data, + mem::ManuallyDrop::new(data), )) } @@ -436,7 +436,50 @@ impl Env { value: raw_value, value_type: ValueType::Object, }), - data, + mem::ManuallyDrop::new(data), + )) + } + + #[inline] + /// # Safety + /// Mostly the same with `create_arraybuffer_with_data` + /// + /// Provided `finalize_callback` will be called when `Buffer` got dropped. + /// + /// You can pass in `noop_finalize` if you have nothing to do in finalize phase. + pub unsafe fn create_arraybuffer_with_borrowed_data( + &self, + data: *const u8, + length: usize, + hint: Hint, + finalize_callback: Finalize, + ) -> Result + where + Finalize: FnOnce(Hint, Env), + { + let mut raw_value = ptr::null_mut(); + check_status!(sys::napi_create_external_arraybuffer( + self.0, + data as *mut c_void, + length, + Some( + raw_finalize_with_custom_callback:: + as unsafe extern "C" fn( + env: sys::napi_env, + finalize_data: *mut c_void, + finalize_hint: *mut c_void, + ) + ), + Box::into_raw(Box::new((hint, finalize_callback))) as *mut c_void, + &mut raw_value, + ))?; + Ok(JsArrayBufferValue::new( + JsArrayBuffer(Value { + env: self.0, + value: raw_value, + value_type: ValueType::Object, + }), + mem::ManuallyDrop::new(Vec::from_raw_parts(data as *mut u8, length, length)), )) } diff --git a/napi/src/js_values/arraybuffer.rs b/napi/src/js_values/arraybuffer.rs index e0c89f70..4a8dd8d4 100644 --- a/napi/src/js_values/arraybuffer.rs +++ b/napi/src/js_values/arraybuffer.rs @@ -2,10 +2,10 @@ use std::mem; use std::ops::{Deref, DerefMut}; use std::os::raw::c_void; use std::ptr; +use std::slice; use super::{Value, ValueType}; -use crate::check_status; -use crate::{sys, JsUnknown, NapiValue, Ref, Result}; +use crate::{check_status, sys, JsUnknown, NapiValue, Ref, Result}; pub struct JsArrayBuffer(pub(crate) Value); @@ -18,7 +18,7 @@ pub struct JsTypedArray(pub(crate) Value); pub struct JsTypedArrayValue { pub arraybuffer: JsArrayBuffer, - _data: *mut c_void, + data: *mut c_void, pub byte_offset: u64, pub length: u64, pub typedarray_type: TypedArrayType, @@ -164,11 +164,8 @@ impl JsArrayBuffer { impl JsArrayBufferValue { #[inline] - pub fn new(value: JsArrayBuffer, data: Vec) -> Self { - JsArrayBufferValue { - value, - data: mem::ManuallyDrop::new(data), - } + pub fn new(value: JsArrayBuffer, data: mem::ManuallyDrop>) -> Self { + JsArrayBufferValue { value, data } } #[inline] @@ -227,7 +224,7 @@ impl JsTypedArray { })?; Ok(JsTypedArrayValue { - _data: data, + data, length: len, byte_offset, typedarray_type: typedarray_type.into(), @@ -236,6 +233,27 @@ impl JsTypedArray { } } +impl JsTypedArrayValue { + #[inline(always)] + fn as_slice(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.data as *const u8, self.length as usize) } + } +} + +impl AsRef<[u8]> for JsTypedArrayValue { + fn as_ref(&self) -> &[u8] { + self.as_slice() + } +} + +impl Deref for JsTypedArrayValue { + type Target = [u8]; + + fn deref(&self) -> &[u8] { + self.as_slice() + } +} + impl JsDataView { #[inline] pub fn into_value(self) -> Result { diff --git a/napi/src/js_values/mod.rs b/napi/src/js_values/mod.rs index 99b4f99b..62040ae7 100644 --- a/napi/src/js_values/mod.rs +++ b/napi/src/js_values/mod.rs @@ -2,8 +2,7 @@ use std::convert::TryFrom; use std::ffi::CString; use std::ptr; -use crate::check_status; -use crate::{sys, Callback, Error, Result, Status}; +use crate::{check_status, sys, Callback, Error, Result, Status}; #[cfg(feature = "serde-json")] mod de;