neon/sys/
arraybuffer.rs

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    // Safety: Boxing could move the data; must box before grabbing a raw pointer
28    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
51/// # Safety
52/// * Caller must ensure `env` and `buf` are valid
53/// * The lifetime `'a` does not exceed the lifetime of `Env` or `buf`
54pub 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
67/// # Safety
68/// * Caller must ensure `env` and `buf` are valid
69pub 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}