1use std::ffi::c_void;
2use std::mem;
3use std::ops::{Deref, DerefMut};
4use std::ptr;
5use std::sync::{
6 atomic::{AtomicBool, Ordering},
7 Arc,
8};
9
10#[cfg(all(feature = "napi4", not(feature = "noop"), not(target_family = "wasm")))]
11use crate::bindgen_prelude::{CUSTOM_GC_TSFN, CUSTOM_GC_TSFN_DESTROYED, THREADS_CAN_ACCESS_ENV};
12pub use crate::js_values::TypedArrayType;
13use crate::{check_status, sys, Error, Result, Status, ValueType};
14
15use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
16
17#[cfg(target_family = "wasm")]
18extern "C" {
19 fn emnapi_sync_memory(
20 env: crate::sys::napi_env,
21 js_to_wasm: bool,
22 arraybuffer_or_view: crate::sys::napi_value,
23 byte_offset: usize,
24 length: usize,
25 ) -> crate::sys::napi_status;
26}
27
28trait Finalizer {
29 type RustType;
30
31 fn finalizer_notify(&self) -> *mut dyn FnOnce(*mut Self::RustType, usize);
32
33 fn data_managed_type(&self) -> &DataManagedType;
34
35 fn len(&self) -> &usize;
36
37 fn ref_count(&self) -> usize;
38}
39
40macro_rules! impl_typed_array {
41 ($name:ident, $rust_type:ident, $typed_array_type:expr) => {
42 pub struct $name {
43 data: *mut $rust_type,
44 length: usize,
45 data_managed_type: DataManagedType,
46 byte_offset: usize,
47 raw: Option<(crate::sys::napi_ref, crate::sys::napi_env)>,
48 // Use `Arc` for ref count
49 // Use `AtomicBool` for flag to indicate whether the value is dropped in VM
50 drop_in_vm: Arc<AtomicBool>,
51 finalizer_notify: *mut dyn FnOnce(*mut $rust_type, usize),
52 }
53
54 unsafe impl Send for $name {}
55
56 impl Finalizer for $name {
57 type RustType = $rust_type;
58
59 fn finalizer_notify(&self) -> *mut dyn FnOnce(*mut Self::RustType, usize) {
60 self.finalizer_notify
61 }
62
63 fn data_managed_type(&self) -> &DataManagedType {
64 &self.data_managed_type
65 }
66
67 fn len(&self) -> &usize {
68 &self.length
69 }
70
71 fn ref_count(&self) -> usize {
72 Arc::strong_count(&self.drop_in_vm)
73 }
74 }
75
76 impl Drop for $name {
77 fn drop(&mut self) {
78 if Arc::strong_count(&self.drop_in_vm) == 1 {
79 if let Some((ref_, env)) = self.raw {
80 if ref_.is_null() {
81 return;
82 }
83 #[cfg(all(feature = "napi4", not(feature = "noop"), not(target_family = "wasm")))]
84 {
85 if CUSTOM_GC_TSFN_DESTROYED.load(Ordering::SeqCst) {
86 return;
87 }
88 if !THREADS_CAN_ACCESS_ENV
89 .borrow_mut(|m| m.get(&std::thread::current().id()).is_some())
90 {
91 let status = unsafe {
92 sys::napi_call_threadsafe_function(
93 CUSTOM_GC_TSFN.load(std::sync::atomic::Ordering::SeqCst),
94 ref_.cast(),
95 1,
96 )
97 };
98 assert!(
99 status == sys::Status::napi_ok || status == sys::Status::napi_closing,
100 "Call custom GC in ArrayBuffer::drop failed {}",
101 Status::from(status)
102 );
103 return;
104 }
105 }
106 let mut ref_count = 0;
107 crate::check_status_or_throw!(
108 env,
109 unsafe { sys::napi_reference_unref(env, ref_, &mut ref_count) },
110 "Failed to unref ArrayBuffer reference in drop"
111 );
112 debug_assert!(
113 ref_count == 0,
114 "ArrayBuffer reference count in ArrayBuffer::drop is not zero"
115 );
116 crate::check_status_or_throw!(
117 env,
118 unsafe { sys::napi_delete_reference(env, ref_) },
119 "Failed to delete ArrayBuffer reference in drop"
120 );
121 return;
122 }
123 if !self.drop_in_vm.load(Ordering::Acquire) && !self.data.is_null() {
124 match &self.data_managed_type {
125 DataManagedType::Owned => {
126 let length = self.length;
127 unsafe { Vec::from_raw_parts(self.data, length, length) };
128 }
129 DataManagedType::External => {
130 let finalizer = unsafe { Box::from_raw(self.finalizer_notify) };
131 (finalizer)(self.data, self.length);
132 }
133 _ => {}
134 }
135 }
136 }
137 }
138 }
139
140 impl $name {
141 fn noop_finalize(_data: *mut $rust_type, _length: usize) {}
142
143 #[cfg(target_family = "wasm")]
144 pub fn sync(&mut self, env: &crate::Env) {
145 if let Some((reference, _)) = self.raw {
146 let mut value = ptr::null_mut();
147 let mut array_buffer = ptr::null_mut();
148 crate::check_status_or_throw!(
149 env.raw(),
150 unsafe { crate::sys::napi_get_reference_value(env.raw(), reference, &mut value) },
151 "Failed to get reference value from TypedArray while syncing"
152 );
153 crate::check_status_or_throw!(
154 env.raw(),
155 unsafe {
156 crate::sys::napi_get_typedarray_info(
157 env.raw(),
158 value,
159 &mut ($typed_array_type as i32) as *mut i32,
160 &mut self.length as *mut usize,
161 ptr::null_mut(),
162 &mut array_buffer,
163 &mut self.byte_offset as *mut usize,
164 )
165 },
166 "Failed to get ArrayBuffer under the TypedArray while syncing"
167 );
168 crate::check_status_or_throw!(
169 env.raw(),
170 unsafe {
171 emnapi_sync_memory(
172 env.raw(),
173 false,
174 array_buffer,
175 self.byte_offset,
176 self.length,
177 )
178 },
179 "Failed to sync memory"
180 );
181 } else {
182 return;
183 }
184 }
185
186 pub fn new(mut data: Vec<$rust_type>) -> Self {
187 data.shrink_to_fit();
188 let ret = $name {
189 data: data.as_mut_ptr(),
190 length: data.len(),
191 data_managed_type: DataManagedType::Owned,
192 byte_offset: 0,
193 raw: None,
194 drop_in_vm: Arc::new(AtomicBool::new(false)),
195 finalizer_notify: Box::into_raw(Box::new(Self::noop_finalize)),
196 };
197 mem::forget(data);
198 ret
199 }
200
201 pub fn with_data_copied<D>(data: D) -> Self
202 where
203 D: AsRef<[$rust_type]>,
204 {
205 let mut data_copied = data.as_ref().to_vec();
206 let ret = $name {
207 data: data_copied.as_mut_ptr(),
208 length: data.as_ref().len(),
209 data_managed_type: DataManagedType::Owned,
210 finalizer_notify: Box::into_raw(Box::new(Self::noop_finalize)),
211 raw: None,
212 drop_in_vm: Arc::new(AtomicBool::new(false)),
213 byte_offset: 0,
214 };
215 mem::forget(data_copied);
216 ret
217 }
218
219 /// # Safety
220 ///
221 /// The caller will be notified when the data is deallocated by vm
222 pub unsafe fn with_external_data<F>(data: *mut $rust_type, length: usize, notify: F) -> Self
223 where
224 F: 'static + FnOnce(*mut $rust_type, usize),
225 {
226 $name {
227 data,
228 length,
229 data_managed_type: DataManagedType::External,
230 finalizer_notify: Box::into_raw(Box::new(notify)),
231 raw: None,
232 drop_in_vm: Arc::new(AtomicBool::new(false)),
233 byte_offset: 0,
234 }
235 }
236 }
237
238 impl Clone for $name {
239 /// Clone reference, the inner data is not copied nor moved
240 fn clone(&self) -> $name {
241 Self {
242 data: self.data,
243 length: self.length,
244 data_managed_type: self.data_managed_type,
245 finalizer_notify: self.finalizer_notify,
246 raw: self.raw,
247 drop_in_vm: self.drop_in_vm.clone(),
248 byte_offset: self.byte_offset,
249 }
250 }
251 }
252
253 impl Deref for $name {
254 type Target = [$rust_type];
255
256 fn deref(&self) -> &Self::Target {
257 self.as_ref()
258 }
259 }
260
261 impl DerefMut for $name {
262 fn deref_mut(&mut self) -> &mut Self::Target {
263 self.as_mut()
264 }
265 }
266
267 impl AsRef<[$rust_type]> for $name {
268 fn as_ref(&self) -> &[$rust_type] {
269 if self.data.is_null() {
270 return &[];
271 }
272
273 unsafe { std::slice::from_raw_parts(self.data, self.length) }
274 }
275 }
276
277 impl AsMut<[$rust_type]> for $name {
278 fn as_mut(&mut self) -> &mut [$rust_type] {
279 if self.data.is_null() {
280 return &mut [];
281 }
282
283 unsafe { std::slice::from_raw_parts_mut(self.data, self.length) }
284 }
285 }
286
287 impl TypeName for $name {
288 fn type_name() -> &'static str {
289 concat!("TypedArray<", stringify!($rust_type), ">")
290 }
291
292 fn value_type() -> crate::ValueType {
293 crate::ValueType::Object
294 }
295 }
296
297 impl ValidateNapiValue for $name {
298 unsafe fn validate(
299 env: sys::napi_env,
300 napi_val: sys::napi_value,
301 ) -> Result<crate::sys::napi_value> {
302 let mut is_typed_array = false;
303 check_status!(
304 unsafe { sys::napi_is_typedarray(env, napi_val, &mut is_typed_array) },
305 "Failed to check if value is typed array"
306 )?;
307 if !is_typed_array {
308 return Err(Error::new(
309 Status::InvalidArg,
310 "Expected a TypedArray value".to_owned(),
311 ));
312 }
313 Ok(ptr::null_mut())
314 }
315 }
316
317 impl FromNapiValue for $name {
318 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
319 let mut typed_array_type = 0;
320 let mut length = 0;
321 let mut data = ptr::null_mut();
322 let mut array_buffer = ptr::null_mut();
323 let mut byte_offset = 0;
324 let mut ref_ = ptr::null_mut();
325 check_status!(
326 unsafe { sys::napi_create_reference(env, napi_val, 1, &mut ref_) },
327 "Failed to create reference from Buffer"
328 )?;
329 check_status!(
330 unsafe {
331 sys::napi_get_typedarray_info(
332 env,
333 napi_val,
334 &mut typed_array_type,
335 &mut length,
336 &mut data,
337 &mut array_buffer,
338 &mut byte_offset,
339 )
340 },
341 "Get TypedArray info failed"
342 )?;
343 if typed_array_type != $typed_array_type as i32 {
344 return Err(Error::new(
345 Status::InvalidArg,
346 format!("Expected $name, got {}", typed_array_type),
347 ));
348 }
349 Ok($name {
350 data: data as *mut $rust_type,
351 length,
352 byte_offset,
353 raw: Some((ref_, env)),
354 drop_in_vm: Arc::new(AtomicBool::new(true)),
355 data_managed_type: DataManagedType::Vm,
356 finalizer_notify: Box::into_raw(Box::new(Self::noop_finalize)),
357 })
358 }
359 }
360
361 impl ToNapiValue for $name {
362 unsafe fn to_napi_value(env: sys::napi_env, mut val: Self) -> Result<sys::napi_value> {
363 if let Some((ref_, _)) = val.raw {
364 let mut napi_value = std::ptr::null_mut();
365 check_status!(
366 unsafe { sys::napi_get_reference_value(env, ref_, &mut napi_value) },
367 "Failed to get reference from ArrayBuffer"
368 )?;
369 // fast path for ArrayBuffer::drop
370 if Arc::strong_count(&val.drop_in_vm) == 1 {
371 check_status!(
372 unsafe { sys::napi_delete_reference(env, ref_) },
373 "Failed to delete reference in ArrayBuffer::to_napi_value"
374 )?;
375 val.raw = Some((ptr::null_mut(), ptr::null_mut()));
376 }
377 return Ok(napi_value);
378 }
379 let mut arraybuffer_value = ptr::null_mut();
380 let ratio = mem::size_of::<$rust_type>();
381 let val_length = val.length;
382 let length = val_length * ratio;
383 let val_data = val.data;
384 val.drop_in_vm.store(true, Ordering::Release);
385 check_status!(
386 if length == 0 {
387 // Rust uses 0x1 as the data pointer for empty buffers,
388 // but NAPI/V8 only allows multiple buffers to have
389 // the same data pointer if it's 0x0.
390 unsafe {
391 sys::napi_create_arraybuffer(env, length, ptr::null_mut(), &mut arraybuffer_value)
392 }
393 } else {
394 let hint_ptr = Box::into_raw(Box::new(val));
395 let status = unsafe {
396 sys::napi_create_external_arraybuffer(
397 env,
398 val_data.cast(),
399 length,
400 Some(finalizer::<$rust_type, $name>),
401 hint_ptr.cast(),
402 &mut arraybuffer_value,
403 )
404 };
405 if status == napi_sys::Status::napi_no_external_buffers_allowed {
406 let hint = unsafe { Box::from_raw(hint_ptr) };
407 let mut underlying_data = ptr::null_mut();
408 let status = unsafe {
409 sys::napi_create_arraybuffer(
410 env,
411 length,
412 &mut underlying_data,
413 &mut arraybuffer_value,
414 )
415 };
416 unsafe { std::ptr::copy_nonoverlapping(hint.data.cast(), underlying_data, length) };
417 status
418 } else {
419 status
420 }
421 },
422 "Create external arraybuffer failed"
423 )?;
424 let mut napi_val = ptr::null_mut();
425 check_status!(
426 unsafe {
427 sys::napi_create_typedarray(
428 env,
429 $typed_array_type as i32,
430 val_length,
431 arraybuffer_value,
432 0,
433 &mut napi_val,
434 )
435 },
436 "Create TypedArray failed"
437 )?;
438 Ok(napi_val)
439 }
440 }
441
442 impl ToNapiValue for &mut $name {
443 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
444 if let Some((ref_, _)) = val.raw {
445 let mut napi_value = std::ptr::null_mut();
446 check_status!(
447 unsafe { sys::napi_get_reference_value(env, ref_, &mut napi_value) },
448 "Failed to get reference from ArrayBuffer"
449 )?;
450 Ok(napi_value)
451 } else {
452 let cloned_value = $name {
453 drop_in_vm: val.drop_in_vm.clone(),
454 data: val.data,
455 length: val.length,
456 data_managed_type: val.data_managed_type,
457 finalizer_notify: Box::into_raw(Box::new($name::noop_finalize)),
458 raw: None,
459 byte_offset: val.byte_offset,
460 };
461 unsafe { ToNapiValue::to_napi_value(env, cloned_value) }
462 }
463 }
464 }
465 };
466}
467
468macro_rules! impl_from_slice {
469 ($name:ident, $rust_type:ident, $typed_array_type:expr) => {
470 impl FromNapiValue for &mut [$rust_type] {
471 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
472 let mut typed_array_type = 0;
473 let mut length = 0;
474 let mut data = ptr::null_mut();
475 let mut array_buffer = ptr::null_mut();
476 let mut byte_offset = 0;
477 check_status!(
478 unsafe {
479 sys::napi_get_typedarray_info(
480 env,
481 napi_val,
482 &mut typed_array_type,
483 &mut length,
484 &mut data,
485 &mut array_buffer,
486 &mut byte_offset,
487 )
488 },
489 "Get TypedArray info failed"
490 )?;
491 if typed_array_type != $typed_array_type as i32 {
492 return Err(Error::new(
493 Status::InvalidArg,
494 format!("Expected $name, got {}", typed_array_type),
495 ));
496 }
497 Ok(if length == 0 {
498 &mut []
499 } else {
500 unsafe { core::slice::from_raw_parts_mut(data as *mut $rust_type, length) }
501 })
502 }
503 }
504
505 impl FromNapiValue for &[$rust_type] {
506 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
507 let mut typed_array_type = 0;
508 let mut length = 0;
509 let mut data = ptr::null_mut();
510 let mut array_buffer = ptr::null_mut();
511 let mut byte_offset = 0;
512 check_status!(
513 unsafe {
514 sys::napi_get_typedarray_info(
515 env,
516 napi_val,
517 &mut typed_array_type,
518 &mut length,
519 &mut data,
520 &mut array_buffer,
521 &mut byte_offset,
522 )
523 },
524 "Get TypedArray info failed"
525 )?;
526 if typed_array_type != $typed_array_type as i32 {
527 return Err(Error::new(
528 Status::InvalidArg,
529 format!("Expected $name, got {}", typed_array_type),
530 ));
531 }
532 Ok(if length == 0 {
533 &[]
534 } else {
535 unsafe { core::slice::from_raw_parts_mut(data as *mut $rust_type, length) }
536 })
537 }
538 }
539
540 impl TypeName for &mut [$rust_type] {
541 fn type_name() -> &'static str {
542 concat!("TypedArray<", stringify!($rust_type), ">")
543 }
544
545 fn value_type() -> crate::ValueType {
546 crate::ValueType::Object
547 }
548 }
549
550 impl TypeName for &[$rust_type] {
551 fn type_name() -> &'static str {
552 concat!("TypedArray<", stringify!($rust_type), ">")
553 }
554
555 fn value_type() -> crate::ValueType {
556 crate::ValueType::Object
557 }
558 }
559
560 impl ValidateNapiValue for &[$rust_type] {
561 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
562 let mut is_typed_array = false;
563 check_status!(
564 unsafe { sys::napi_is_typedarray(env, napi_val, &mut is_typed_array) },
565 "Failed to validate napi typed array"
566 )?;
567 if !is_typed_array {
568 return Err(Error::new(
569 Status::InvalidArg,
570 "Expected a TypedArray value".to_owned(),
571 ));
572 }
573 Ok(ptr::null_mut())
574 }
575 }
576
577 impl ValidateNapiValue for &mut [$rust_type] {
578 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
579 let mut is_typed_array = false;
580 check_status!(
581 unsafe { sys::napi_is_typedarray(env, napi_val, &mut is_typed_array) },
582 "Failed to validate napi typed array"
583 )?;
584 if !is_typed_array {
585 return Err(Error::new(
586 Status::InvalidArg,
587 "Expected a TypedArray value".to_owned(),
588 ));
589 }
590 Ok(ptr::null_mut())
591 }
592 }
593 };
594}
595
596unsafe extern "C" fn finalizer<Data, T: Finalizer<RustType = Data>>(
597 _env: sys::napi_env,
598 finalize_data: *mut c_void,
599 finalize_hint: *mut c_void,
600) {
601 let data: T = unsafe { *Box::from_raw(finalize_hint as *mut T) };
602 let data_managed_type: DataManagedType = *data.data_managed_type();
603 let length: usize = *data.len();
604 match data_managed_type {
605 DataManagedType::Vm => {
606 // do nothing
607 }
608 DataManagedType::Owned => {
609 if data.ref_count() == 1 {
610 unsafe { Vec::from_raw_parts(ptr:finalize_data as *mut Data, length, capacity:length) };
611 }
612 }
613 DataManagedType::External => {
614 if data.ref_count() == 1 {
615 let finalizer_notify: Box = unsafe { Box::from_raw(data.finalizer_notify()) };
616 (finalizer_notify)(finalize_data as *mut Data, length);
617 }
618 }
619 }
620}
621
622#[derive(PartialEq, Eq, Clone, Copy)]
623enum DataManagedType {
624 /// Vm managed data, passed in from JavaScript
625 Vm,
626 /// Rust owned data, which need to be deallocated in the finalizer
627 Owned,
628 /// External data, which need to be notice to the owner in finalizer
629 External,
630}
631
632impl_typed_array!(Int8Array, i8, TypedArrayType::Int8);
633impl_from_slice!(Int8Array, i8, TypedArrayType::Int8);
634impl_typed_array!(Uint8Array, u8, TypedArrayType::Uint8);
635impl_from_slice!(Uint8Array, u8, TypedArrayType::Uint8);
636impl_typed_array!(Uint8ClampedArray, u8, TypedArrayType::Uint8Clamped);
637impl_typed_array!(Int16Array, i16, TypedArrayType::Int16);
638impl_from_slice!(Int16Array, i16, TypedArrayType::Int16);
639impl_typed_array!(Uint16Array, u16, TypedArrayType::Uint16);
640impl_from_slice!(Uint16Array, u16, TypedArrayType::Uint16);
641impl_typed_array!(Int32Array, i32, TypedArrayType::Int32);
642impl_from_slice!(Int32Array, i32, TypedArrayType::Int32);
643impl_typed_array!(Uint32Array, u32, TypedArrayType::Uint32);
644impl_from_slice!(Uint32Array, u32, TypedArrayType::Uint32);
645impl_typed_array!(Float32Array, f32, TypedArrayType::Float32);
646impl_from_slice!(Float32Array, f32, TypedArrayType::Float32);
647impl_typed_array!(Float64Array, f64, TypedArrayType::Float64);
648impl_from_slice!(Float64Array, f64, TypedArrayType::Float64);
649#[cfg(feature = "napi6")]
650impl_typed_array!(BigInt64Array, i64, TypedArrayType::BigInt64);
651#[cfg(feature = "napi6")]
652impl_from_slice!(BigInt64Array, i64, TypedArrayType::BigInt64);
653#[cfg(feature = "napi6")]
654impl_typed_array!(BigUint64Array, u64, TypedArrayType::BigUint64);
655#[cfg(feature = "napi6")]
656impl_from_slice!(BigUint64Array, u64, TypedArrayType::BigUint64);
657
658/// Zero copy Uint8ClampedArray slice shared between Rust and Node.js.
659/// It can only be used in non-async context and the lifetime is bound to the fn closure.
660/// If you want to use Node.js `Uint8ClampedArray` in async context or want to extend the lifetime, use `Uint8ClampedArray` instead.
661pub struct Uint8ClampedSlice<'scope> {
662 pub(crate) inner: &'scope mut [u8],
663 raw_value: sys::napi_value,
664}
665
666impl<'scope> FromNapiValue for Uint8ClampedSlice<'scope> {
667 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
668 let mut typed_array_type = 0;
669 let mut length = 0;
670 let mut data = ptr::null_mut();
671 let mut array_buffer = ptr::null_mut();
672 let mut byte_offset = 0;
673 check_status!(
674 unsafe {
675 sys::napi_get_typedarray_info(
676 env,
677 napi_val,
678 &mut typed_array_type,
679 &mut length,
680 &mut data,
681 &mut array_buffer,
682 &mut byte_offset,
683 )
684 },
685 "Get TypedArray info failed"
686 )?;
687 if typed_array_type != TypedArrayType::Uint8Clamped as i32 {
688 return Err(Error::new(
689 Status::InvalidArg,
690 format!("Expected $name, got {}", typed_array_type),
691 ));
692 }
693 Ok(Self {
694 inner: if length == 0 {
695 &mut []
696 } else {
697 unsafe { core::slice::from_raw_parts_mut(data.cast(), length) }
698 },
699 raw_value: napi_val,
700 })
701 }
702}
703
704impl ToNapiValue for Uint8ClampedSlice<'_> {
705 #[allow(unused_variables)]
706 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
707 Ok(val.raw_value)
708 }
709}
710
711impl TypeName for Uint8ClampedSlice<'_> {
712 fn type_name() -> &'static str {
713 "Uint8ClampedArray"
714 }
715
716 fn value_type() -> ValueType {
717 ValueType::Object
718 }
719}
720
721impl ValidateNapiValue for Uint8ClampedSlice<'_> {
722 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
723 let mut is_typedarray: bool = false;
724 check_status!(
725 unsafe { sys::napi_is_typedarray(env, napi_val, &mut is_typedarray) },
726 "Failed to validate typed buffer"
727 )?;
728 if !is_typedarray {
729 return Err(Error::new(
730 Status::InvalidArg,
731 reason:"Expected a TypedArray value".to_owned(),
732 ));
733 }
734 Ok(ptr::null_mut())
735 }
736}
737
738impl AsRef<[u8]> for Uint8ClampedSlice<'_> {
739 fn as_ref(&self) -> &[u8] {
740 self.inner
741 }
742}
743
744impl<'scope> Deref for Uint8ClampedSlice<'scope> {
745 type Target = [u8];
746
747 fn deref(&self) -> &Self::Target {
748 self.inner
749 }
750}
751
752impl<'scope> DerefMut for Uint8ClampedSlice<'scope> {
753 fn deref_mut(&mut self) -> &mut Self::Target {
754 self.inner
755 }
756}
757
758impl<T: Into<Vec<u8>>> From<T> for Uint8Array {
759 fn from(data: T) -> Self {
760 Uint8Array::new(data.into())
761 }
762}
763
764impl<T: Into<Vec<u8>>> From<T> for Uint8ClampedArray {
765 fn from(data: T) -> Self {
766 Uint8ClampedArray::new(data.into())
767 }
768}
769
770impl<T: Into<Vec<u16>>> From<T> for Uint16Array {
771 fn from(data: T) -> Self {
772 Uint16Array::new(data.into())
773 }
774}
775
776impl<T: Into<Vec<u32>>> From<T> for Uint32Array {
777 fn from(data: T) -> Self {
778 Uint32Array::new(data.into())
779 }
780}
781
782impl<T: Into<Vec<i8>>> From<T> for Int8Array {
783 fn from(data: T) -> Self {
784 Int8Array::new(data.into())
785 }
786}
787
788impl<T: Into<Vec<i16>>> From<T> for Int16Array {
789 fn from(data: T) -> Self {
790 Int16Array::new(data.into())
791 }
792}
793
794impl<T: Into<Vec<i32>>> From<T> for Int32Array {
795 fn from(data: T) -> Self {
796 Int32Array::new(data.into())
797 }
798}
799
800impl<T: Into<Vec<f32>>> From<T> for Float32Array {
801 fn from(data: T) -> Self {
802 Float32Array::new(data.into())
803 }
804}
805
806impl<T: Into<Vec<f64>>> From<T> for Float64Array {
807 fn from(data: T) -> Self {
808 Float64Array::new(data.into())
809 }
810}
811
812#[cfg(feature = "napi6")]
813impl<T: Into<Vec<i64>>> From<T> for BigInt64Array {
814 fn from(data: T) -> Self {
815 BigInt64Array::new(data.into())
816 }
817}
818#[cfg(feature = "napi6")]
819impl<T: Into<Vec<u64>>> From<T> for BigUint64Array {
820 fn from(data: T) -> Self {
821 BigUint64Array::new(data.into())
822 }
823}
824