1use std::ops::{Deref, DerefMut};
2use std::os::raw::c_void;
3use std::ptr;
4use std::slice;
5
6use crate::{
7 bindgen_runtime::{FromNapiValue, TypeName, TypedArrayType, ValidateNapiValue},
8 check_status, sys, Env, Error, NapiValue, Ref, Result, Status, Unknown, Value, ValueType,
9};
10
11use super::JsValue;
12
13#[deprecated(
14 since = "3.0.0",
15 note = "Use `napi::bindgen_prelude::ArrayBuffer` instead"
16)]
17pub struct JsArrayBuffer(pub(crate) Value);
18
19impl TypeName for JsArrayBuffer {
20 fn type_name() -> &'static str {
21 "ArrayBuffer"
22 }
23
24 fn value_type() -> ValueType {
25 ValueType::Object
26 }
27}
28
29impl ValidateNapiValue for JsArrayBuffer {
30 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
31 let mut is_array_buffer = false;
32 check_status!(unsafe { sys::napi_is_arraybuffer(env, napi_val, &mut is_array_buffer) })?;
33 if !is_array_buffer {
34 return Err(Error::new(
35 Status::InvalidArg,
36 "Value is not an array buffer".to_owned(),
37 ));
38 }
39 Ok(ptr::null_mut())
40 }
41}
42
43impl FromNapiValue for JsArrayBuffer {
44 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
45 Ok(Self(Value {
46 env,
47 value: napi_val,
48 value_type: ValueType::Object,
49 }))
50 }
51}
52
53impl JsValue<'_> for JsArrayBuffer {
54 fn value(&self) -> Value {
55 self.0
56 }
57}
58
59#[deprecated(
60 since = "3.0.0",
61 note = "Use `napi::bindgen_prelude::ArrayBuffer` instead"
62)]
63pub struct JsArrayBufferValue {
64 pub value: JsArrayBuffer,
65 pub(crate) len: usize,
66 pub(crate) data: *mut c_void,
67}
68
69#[deprecated(
70 since = "3.0.0",
71 note = "Use `napi::bindgen_prelude::Uint8Array/Int8Array...` instead"
72)]
73pub struct JsTypedArray(pub(crate) Value);
74
75impl TypeName for JsTypedArray {
76 fn type_name() -> &'static str {
77 "TypedArray"
78 }
79
80 fn value_type() -> ValueType {
81 ValueType::Object
82 }
83}
84
85impl FromNapiValue for JsTypedArray {
86 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
87 Ok(Self(Value {
88 env,
89 value: napi_val,
90 value_type: ValueType::Object,
91 }))
92 }
93}
94
95impl JsValue<'_> for JsTypedArray {
96 fn value(&self) -> Value {
97 self.0
98 }
99}
100
101#[deprecated(
102 since = "3.0.0",
103 note = "Use `napi::bindgen_prelude::Uint8Array/Int8Array...` instead"
104)]
105pub struct JsTypedArrayValue {
106 pub arraybuffer: JsArrayBuffer,
107 data: *mut c_void,
108 pub byte_offset: usize,
109 pub length: usize,
110 pub typedarray_type: TypedArrayType,
111}
112
113pub struct JsDataView(pub(crate) Value);
114
115impl TypeName for JsDataView {
116 fn type_name() -> &'static str {
117 "DataView"
118 }
119
120 fn value_type() -> ValueType {
121 ValueType::Object
122 }
123}
124
125pub struct JsDataViewValue {
126 pub arraybuffer: JsArrayBuffer,
127 _data: *mut c_void,
128 pub byte_offset: u64,
129 pub length: u64,
130}
131
132impl JsArrayBuffer {
133 #[cfg(feature = "napi7")]
134 pub fn detach(self) -> Result<()> {
135 check_status!(unsafe { sys::napi_detach_arraybuffer(self.0.env, self.0.value) })
136 }
137
138 #[cfg(feature = "napi7")]
139 pub fn is_detached(&self) -> Result<bool> {
140 let mut is_detached = false;
141 check_status!(unsafe {
142 sys::napi_is_detached_arraybuffer(self.0.env, self.0.value, &mut is_detached)
143 })?;
144 Ok(is_detached)
145 }
146
147 pub fn into_value(self) -> Result<JsArrayBufferValue> {
148 let mut data = ptr::null_mut();
149 let mut len: usize = 0;
150 check_status!(unsafe {
151 sys::napi_get_arraybuffer_info(self.0.env, self.0.value, &mut data, &mut len)
152 })?;
153 Ok(JsArrayBufferValue {
154 data,
155 value: self,
156 len,
157 })
158 }
159
160 pub fn into_typedarray(
161 self,
162 typedarray_type: TypedArrayType,
163 length: usize,
164 byte_offset: usize,
165 ) -> Result<JsTypedArray> {
166 let mut typedarray_value = ptr::null_mut();
167 check_status!(unsafe {
168 sys::napi_create_typedarray(
169 self.0.env,
170 typedarray_type.into(),
171 length,
172 self.0.value,
173 byte_offset,
174 &mut typedarray_value,
175 )
176 })?;
177 Ok(JsTypedArray(Value {
178 env: self.0.env,
179 value: typedarray_value,
180 value_type: ValueType::Object,
181 }))
182 }
183
184 pub fn into_dataview(self, length: usize, byte_offset: usize) -> Result<JsDataView> {
185 let mut dataview_value = ptr::null_mut();
186 check_status!(unsafe {
187 sys::napi_create_dataview(
188 self.0.env,
189 length,
190 self.0.value,
191 byte_offset,
192 &mut dataview_value,
193 )
194 })?;
195 Ok(JsDataView(Value {
196 env: self.0.env,
197 value: dataview_value,
198 value_type: ValueType::Object,
199 }))
200 }
201
202 pub fn into_ref(self) -> Result<Ref<JsArrayBuffer>> {
203 Ref::new(&Env::from(self.0.env), &self)
204 }
205}
206
207impl JsArrayBufferValue {
208 pub fn new(value: JsArrayBuffer, data: *mut c_void, len: usize) -> Self {
209 JsArrayBufferValue { value, len, data }
210 }
211
212 pub fn into_raw(self) -> JsArrayBuffer {
213 self.value
214 }
215
216 pub fn into_unknown<'env>(self) -> Unknown<'env> {
217 unsafe { Unknown::from_raw_unchecked(self.value.0.env, self.value.0.value) }
218 }
219}
220
221impl AsRef<[u8]> for JsArrayBufferValue {
222 fn as_ref(&self) -> &[u8] {
223 if self.data.is_null() {
224 return &[];
225 }
226 unsafe { slice::from_raw_parts(self.data as *const u8, self.len) }
227 }
228}
229
230impl AsMut<[u8]> for JsArrayBufferValue {
231 fn as_mut(&mut self) -> &mut [u8] {
232 if self.data.is_null() {
233 return &mut [];
234 }
235 unsafe { slice::from_raw_parts_mut(self.data as *mut u8, self.len) }
236 }
237}
238
239impl Deref for JsArrayBufferValue {
240 type Target = [u8];
241
242 fn deref(&self) -> &Self::Target {
243 self.as_ref()
244 }
245}
246
247impl DerefMut for JsArrayBufferValue {
248 fn deref_mut(&mut self) -> &mut Self::Target {
249 self.as_mut()
250 }
251}
252
253impl JsTypedArray {
254 pub fn into_value(self) -> Result<JsTypedArrayValue> {
259 let mut typedarray_type = 0;
260 let mut len = 0;
261 let mut data = ptr::null_mut();
262 let mut arraybuffer_value = ptr::null_mut();
263 let mut byte_offset = 0;
264 check_status!(unsafe {
265 sys::napi_get_typedarray_info(
266 self.0.env,
267 self.0.value,
268 &mut typedarray_type,
269 &mut len,
270 &mut data,
271 &mut arraybuffer_value,
272 &mut byte_offset,
273 )
274 })?;
275
276 Ok(JsTypedArrayValue {
277 data,
278 length: len,
279 byte_offset,
280 typedarray_type: typedarray_type.into(),
281 arraybuffer: unsafe { JsArrayBuffer::from_raw_unchecked(self.0.env, arraybuffer_value) },
282 })
283 }
284}
285
286impl JsTypedArrayValue {
287 #[inline]
288 fn is_valid_as_ref(&self, dest_type: TypedArrayType) {
289 if self.typedarray_type == TypedArrayType::Uint8Clamped && dest_type == TypedArrayType::Uint8 {
291 return;
292 }
293 if self.typedarray_type != dest_type {
294 panic!(
295 "invalid typedarray type: expected {:?}, got {:?}",
296 dest_type, self.typedarray_type
297 );
298 }
299 }
300}
301
302macro_rules! impl_as_ref {
303 ($ref_type:ident, $expect_type:expr) => {
304 impl AsRef<[$ref_type]> for JsTypedArrayValue {
305 fn as_ref(&self) -> &[$ref_type] {
306 self.is_valid_as_ref($expect_type);
307 if self.data.is_null() {
308 return &[];
309 }
310 unsafe { slice::from_raw_parts(self.data as *const $ref_type, self.length) }
311 }
312 }
313
314 impl AsMut<[$ref_type]> for JsTypedArrayValue {
315 fn as_mut(&mut self) -> &mut [$ref_type] {
316 self.is_valid_as_ref($expect_type);
317 if self.data.is_null() {
318 return &mut [];
319 }
320 unsafe { slice::from_raw_parts_mut(self.data as *mut $ref_type, self.length) }
321 }
322 }
323 };
324}
325
326impl_as_ref!(u8, TypedArrayType::Uint8);
327impl_as_ref!(i8, TypedArrayType::Int8);
328impl_as_ref!(u16, TypedArrayType::Uint16);
329impl_as_ref!(i16, TypedArrayType::Int16);
330impl_as_ref!(u32, TypedArrayType::Uint32);
331impl_as_ref!(i32, TypedArrayType::Int32);
332impl_as_ref!(f32, TypedArrayType::Float32);
333impl_as_ref!(f64, TypedArrayType::Float64);
334#[cfg(feature = "napi6")]
335impl_as_ref!(i64, TypedArrayType::BigInt64);
336#[cfg(feature = "napi6")]
337impl_as_ref!(u64, TypedArrayType::BigUint64);
338
339impl JsDataView {
340 pub fn into_value(self) -> Result<JsDataViewValue> {
341 let mut length = 0u64;
342 let mut byte_offset = 0u64;
343 let mut arraybuffer_value = ptr::null_mut();
344 let mut data = ptr::null_mut();
345
346 check_status!(unsafe {
347 sys::napi_get_dataview_info(
348 self.0.env,
349 self.0.value,
350 &mut length as *mut u64 as *mut _,
351 &mut data,
352 &mut arraybuffer_value,
353 &mut byte_offset as *mut u64 as *mut _,
354 )
355 })?;
356 Ok(JsDataViewValue {
357 arraybuffer: unsafe { JsArrayBuffer::from_raw_unchecked(self.0.env, arraybuffer_value) },
358 byte_offset,
359 length,
360 _data: data,
361 })
362 }
363}