1#[cfg(feature = "external-buffers")]
2use std::os::raw::c_void;
3use std::{mem::MaybeUninit, ptr::null_mut, slice};
4
5use super::{
6 bindings as napi,
7 raw::{Env, Local},
8};
9
10pub unsafe fn new(env: Env, len: usize) -> Result<Local, napi::Status> {
11 let mut buf = MaybeUninit::uninit();
12 let status = napi::create_arraybuffer(env, len, null_mut(), buf.as_mut_ptr());
13
14 match status {
15 Err(err @ napi::Status::PendingException) => return Err(err),
16 status => status.unwrap(),
17 };
18
19 Ok(buf.assume_init())
20}
21
22#[cfg(feature = "external-buffers")]
23pub unsafe fn new_external<T>(env: Env, data: T) -> Local
24where
25 T: AsMut<[u8]> + Send,
26{
27 let mut data = Box::new(data);
29 let buf = data.as_mut().as_mut();
30 let length = buf.len();
31 let mut result = MaybeUninit::uninit();
32
33 napi::create_external_arraybuffer(
34 env,
35 buf.as_mut_ptr() as *mut _,
36 length,
37 Some(drop_external::<T>),
38 Box::into_raw(data) as *mut _,
39 result.as_mut_ptr(),
40 )
41 .unwrap();
42
43 result.assume_init()
44}
45
46#[cfg(feature = "external-buffers")]
47unsafe extern "C" fn drop_external<T>(_env: Env, _data: *mut c_void, hint: *mut c_void) {
48 drop(Box::<T>::from_raw(hint as *mut _));
49}
50
51pub unsafe fn as_mut_slice<'a>(env: Env, buf: Local) -> &'a mut [u8] {
55 let mut data = MaybeUninit::uninit();
56 let mut size = 0usize;
57
58 napi::get_arraybuffer_info(env, buf, data.as_mut_ptr(), &mut size as *mut _).unwrap();
59
60 if size == 0 {
61 return &mut [];
62 }
63
64 slice::from_raw_parts_mut(data.assume_init().cast(), size)
65}
66
67pub unsafe fn size(env: Env, buf: Local) -> usize {
70 let mut data = MaybeUninit::uninit();
71 let mut size = 0usize;
72
73 napi::get_arraybuffer_info(env, buf, data.as_mut_ptr(), &mut size as *mut _).unwrap();
74
75 size
76}