yuuang_test_napi/js_values/
arraybuffer.rs

1use std::ops::{Deref, DerefMut};
2use std::os::raw::c_void;
3use std::ptr;
4use std::slice;
5
6use crate::{check_status, sys, JsUnknown, NapiValue, Ref, Result, Value, ValueType};
7
8pub struct JsArrayBuffer(pub(crate) Value);
9
10pub struct JsArrayBufferValue {
11  pub(crate) value: JsArrayBuffer,
12  len: usize,
13  data: *mut c_void,
14}
15
16pub struct JsTypedArray(pub(crate) Value);
17
18pub struct JsTypedArrayValue {
19  pub arraybuffer: JsArrayBuffer,
20  data: *mut c_void,
21  pub byte_offset: u64,
22  pub length: u64,
23  pub typedarray_type: TypedArrayType,
24}
25
26pub struct JsDataView(pub(crate) Value);
27
28pub struct JsDataViewValue {
29  pub arraybuffer: JsArrayBuffer,
30  _data: *mut c_void,
31  pub byte_offset: u64,
32  pub length: u64,
33}
34
35#[repr(i32)]
36#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
37#[non_exhaustive]
38pub enum TypedArrayType {
39  Int8 = 0,
40  Uint8,
41  Uint8Clamped,
42  Int16,
43  Uint16,
44  Int32,
45  Uint32,
46  Float32,
47  Float64,
48  #[cfg(feature = "napi6")]
49  BigInt64,
50  #[cfg(feature = "napi6")]
51  BigUint64,
52
53  /// compatible with higher versions
54  Unknown = 1024,
55}
56
57impl From<sys::napi_typedarray_type> for TypedArrayType {
58  fn from(value: sys::napi_typedarray_type) -> Self {
59    match value {
60      sys::TypedarrayType::napi_int8_array => Self::Int8,
61      sys::TypedarrayType::napi_uint8_array => Self::Uint8,
62      sys::TypedarrayType::napi_uint8_clamped_array => Self::Uint8Clamped,
63      sys::TypedarrayType::napi_int16_array => Self::Int16,
64      sys::TypedarrayType::napi_uint16_array => Self::Uint16,
65      sys::TypedarrayType::napi_int32_array => Self::Int32,
66      sys::TypedarrayType::napi_uint32_array => Self::Uint32,
67      sys::TypedarrayType::napi_float32_array => Self::Float32,
68      sys::TypedarrayType::napi_float64_array => Self::Float64,
69      #[cfg(feature = "napi6")]
70      sys::TypedarrayType::napi_bigint64_array => Self::BigInt64,
71      #[cfg(feature = "napi6")]
72      sys::TypedarrayType::napi_biguint64_array => Self::BigUint64,
73      _ => Self::Unknown,
74    }
75  }
76}
77
78impl From<TypedArrayType> for sys::napi_typedarray_type {
79  fn from(value: TypedArrayType) -> sys::napi_typedarray_type {
80    value as i32
81  }
82}
83
84impl JsArrayBuffer {
85  #[cfg(feature = "napi7")]
86  #[inline]
87  pub fn detach(self) -> Result<()> {
88    check_status!(unsafe { sys::napi_detach_arraybuffer(self.0.env, self.0.value) })
89  }
90
91  #[cfg(feature = "napi7")]
92  #[inline]
93  pub fn is_detached(&self) -> Result<bool> {
94    let mut is_detached = false;
95    check_status!(unsafe {
96      sys::napi_is_detached_arraybuffer(self.0.env, self.0.value, &mut is_detached)
97    })?;
98    Ok(is_detached)
99  }
100
101  #[inline]
102  pub fn into_value(self) -> Result<JsArrayBufferValue> {
103    let mut data = ptr::null_mut();
104    let mut len: usize = 0;
105    check_status!(unsafe {
106      sys::napi_get_arraybuffer_info(self.0.env, self.0.value, &mut data, &mut len as *mut usize)
107    })?;
108    Ok(JsArrayBufferValue {
109      data,
110      value: self,
111      len,
112    })
113  }
114
115  #[inline]
116  pub fn into_typedarray(
117    self,
118    typedarray_type: TypedArrayType,
119    length: usize,
120    byte_offset: usize,
121  ) -> Result<JsTypedArray> {
122    let mut typedarray_value = ptr::null_mut();
123    check_status!(unsafe {
124      sys::napi_create_typedarray(
125        self.0.env,
126        typedarray_type.into(),
127        length,
128        self.0.value,
129        byte_offset,
130        &mut typedarray_value,
131      )
132    })?;
133    Ok(JsTypedArray(Value {
134      env: self.0.env,
135      value: typedarray_value,
136      value_type: ValueType::Object,
137    }))
138  }
139
140  #[inline]
141  pub fn into_dataview(self, length: usize, byte_offset: usize) -> Result<JsDataView> {
142    let mut dataview_value = ptr::null_mut();
143    check_status!(unsafe {
144      sys::napi_create_dataview(
145        self.0.env,
146        length,
147        self.0.value,
148        byte_offset,
149        &mut dataview_value,
150      )
151    })?;
152    Ok(JsDataView(Value {
153      env: self.0.env,
154      value: dataview_value,
155      value_type: ValueType::Object,
156    }))
157  }
158
159  #[inline]
160  pub fn into_ref(self) -> Result<Ref<JsArrayBufferValue>> {
161    Ref::new(self.0, 1, self.into_value()?)
162  }
163}
164
165impl JsArrayBufferValue {
166  #[inline]
167  pub fn new(value: JsArrayBuffer, data: *mut c_void, len: usize) -> Self {
168    JsArrayBufferValue { value, len, data }
169  }
170
171  #[inline]
172  pub fn into_raw(self) -> JsArrayBuffer {
173    self.value
174  }
175
176  #[inline]
177  pub fn into_unknown(self) -> JsUnknown {
178    unsafe { JsUnknown::from_raw_unchecked(self.value.0.env, self.value.0.value) }
179  }
180}
181
182impl AsRef<[u8]> for JsArrayBufferValue {
183  fn as_ref(&self) -> &[u8] {
184    unsafe { slice::from_raw_parts(self.data as *const u8, self.len) }
185  }
186}
187
188impl AsMut<[u8]> for JsArrayBufferValue {
189  fn as_mut(&mut self) -> &mut [u8] {
190    unsafe { slice::from_raw_parts_mut(self.data as *mut u8, self.len) }
191  }
192}
193
194impl Deref for JsArrayBufferValue {
195  type Target = [u8];
196
197  fn deref(&self) -> &[u8] {
198    self.as_ref()
199  }
200}
201
202impl DerefMut for JsArrayBufferValue {
203  fn deref_mut(&mut self) -> &mut Self::Target {
204    self.as_mut()
205  }
206}
207
208impl JsTypedArray {
209  /// get TypeArray info
210  /// https://nodejs.org/api/n-api.html#n_api_napi_get_typedarray_info
211  ///
212  /// ***Warning***: Use caution while using this API since the underlying data buffer is managed by the VM.
213  #[inline]
214  pub fn into_value(self) -> Result<JsTypedArrayValue> {
215    let mut typedarray_type = 0;
216    let mut len = 0u64;
217    let mut data = ptr::null_mut();
218    let mut arraybuffer_value = ptr::null_mut();
219    let mut byte_offset = 0u64;
220    check_status!(unsafe {
221      sys::napi_get_typedarray_info(
222        self.0.env,
223        self.0.value,
224        &mut typedarray_type,
225        &mut len as *mut u64 as *mut _,
226        &mut data,
227        &mut arraybuffer_value,
228        &mut byte_offset as *mut u64 as *mut usize,
229      )
230    })?;
231
232    Ok(JsTypedArrayValue {
233      data,
234      length: len,
235      byte_offset,
236      typedarray_type: typedarray_type.into(),
237      arraybuffer: unsafe { JsArrayBuffer::from_raw_unchecked(self.0.env, arraybuffer_value) },
238    })
239  }
240}
241
242macro_rules! impl_as_ref {
243  ($ref_type:ident) => {
244    impl AsRef<[$ref_type]> for JsTypedArrayValue {
245      fn as_ref(&self) -> &[$ref_type] {
246        unsafe { slice::from_raw_parts(self.data as *const $ref_type, self.length as usize) }
247      }
248    }
249
250    impl AsMut<[$ref_type]> for JsTypedArrayValue {
251      fn as_mut(&mut self) -> &mut [$ref_type] {
252        unsafe { slice::from_raw_parts_mut(self.data as *mut $ref_type, self.length as usize) }
253      }
254    }
255  };
256}
257
258impl_as_ref!(u8);
259impl_as_ref!(i8);
260impl_as_ref!(u16);
261impl_as_ref!(i16);
262impl_as_ref!(u32);
263impl_as_ref!(i32);
264impl_as_ref!(f32);
265impl_as_ref!(f64);
266#[cfg(feature = "napi6")]
267impl_as_ref!(i64);
268#[cfg(feature = "napi6")]
269impl_as_ref!(u64);
270
271impl JsDataView {
272  #[inline]
273  pub fn into_value(self) -> Result<JsDataViewValue> {
274    let mut length = 0u64;
275    let mut byte_offset = 0u64;
276    let mut arraybuffer_value = ptr::null_mut();
277    let mut data = ptr::null_mut();
278
279    check_status!(unsafe {
280      sys::napi_get_dataview_info(
281        self.0.env,
282        self.0.value,
283        &mut length as *mut u64 as *mut _,
284        &mut data,
285        &mut arraybuffer_value,
286        &mut byte_offset as *mut u64 as *mut _,
287      )
288    })?;
289    Ok(JsDataViewValue {
290      arraybuffer: unsafe { JsArrayBuffer::from_raw_unchecked(self.0.env, arraybuffer_value) },
291      byte_offset,
292      length,
293      _data: data,
294    })
295  }
296}