1use std::ptr;
2use std::ops::Deref;
3
4use tracing::trace;
5
6use crate::TryIntoJs;
7use crate::JSValue;
8use crate::sys::{napi_value, napi_ref, napi_env};
9use crate::val::JsEnv;
10use crate::NjError;
11
12pub struct ArrayBuffer {
14 data: Vec<u8>,
15}
16
17use std::fmt;
18use std::fmt::Debug;
19
20impl Debug for ArrayBuffer {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 f.write_fmt(format_args!("ArrayBuffer len: {}", self.data.len()))
23 }
24}
25
26impl ArrayBuffer {
27 pub fn new(data: Vec<u8>) -> Self {
28 Self { data }
29 }
30
31 extern "C" fn finalize_buffer(
32 _env: napi_env,
33 _finalize_data: *mut ::std::os::raw::c_void,
34 finalize_hint: *mut ::std::os::raw::c_void,
35 ) {
36 trace!("finalize array buffer");
37 unsafe {
38 let ptr: *mut Vec<u8> = finalize_hint as *mut Vec<u8>;
40 let _rust = Box::from_raw(ptr);
41 }
42 }
43}
44
45impl TryIntoJs for ArrayBuffer {
46 fn try_to_js(self, js_env: &JsEnv) -> Result<napi_value, NjError> {
47 let len = self.data.len();
48
49 let box_data = Box::new(self.data);
50
51 let mut napi_buffer = ptr::null_mut();
52
53 let data_buffer = box_data.as_ptr();
55
56 let data_box_ptr = Box::into_raw(box_data) as *mut core::ffi::c_void;
58
59 crate::napi_call_result!(crate::sys::napi_create_external_arraybuffer(
60 js_env.inner(),
61 data_buffer as *mut core::ffi::c_void,
62 len,
63 Some(Self::finalize_buffer),
64 data_box_ptr,
65 &mut napi_buffer
66 ))?;
67
68 Ok(napi_buffer)
69 }
70}
71
72impl<'a> JSValue<'a> for &'a [u8] {
73 fn convert_to_rust(env: &'a JsEnv, js_value: napi_value) -> Result<Self, NjError> {
74 if !env.is_buffer(js_value)? {
76 return Err(NjError::InvalidType(
77 "Buffer".to_owned(),
78 env.value_type_string(js_value)?.to_owned(),
79 ));
80 }
81
82 let buffer = env.get_buffer_info(js_value)?;
83
84 Ok(buffer)
85 }
86}
87
88pub struct JSArrayBuffer {
113 env: JsEnv,
114 napi_ref: napi_ref,
115 buffer: &'static [u8],
116}
117
118unsafe impl Send for JSArrayBuffer {}
119
120impl JSArrayBuffer {
121 pub fn as_bytes(&self) -> &[u8] {
122 self.buffer
123 }
124}
125
126impl JSValue<'_> for JSArrayBuffer {
127 fn convert_to_rust(env: &JsEnv, napi_value: napi_value) -> Result<Self, NjError> {
128 use std::mem::transmute;
129
130 let napi_ref = env.create_reference(napi_value, 1)?;
131
132 let buffer: &'static [u8] =
134 unsafe { transmute::<&[u8], &'static [u8]>(env.convert_to_rust(napi_value)?) };
135 Ok(Self {
136 env: *env,
137 napi_ref,
138 buffer,
139 })
140 }
141}
142
143impl Drop for JSArrayBuffer {
144 fn drop(&mut self) {
145 self.env
146 .delete_reference(self.napi_ref)
147 .expect("reference can't be deleted to array buf");
148 }
149}
150
151impl Deref for JSArrayBuffer {
152 type Target = [u8];
153
154 fn deref(&self) -> &Self::Target {
155 self.buffer
156 }
157}