napi_h/bindgen_runtime/js_values/
arraybuffer.rs

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) {
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        unsafe { std::slice::from_raw_parts(self.data, self.length) }
258      }
259    }
260
261    impl DerefMut for $name {
262      fn deref_mut(&mut self) -> &mut Self::Target {
263        unsafe { std::slice::from_raw_parts_mut(self.data, self.length) }
264      }
265    }
266
267    impl AsRef<[$rust_type]> for $name {
268      fn as_ref(&self) -> &[$rust_type] {
269        unsafe { std::slice::from_raw_parts(self.data, self.length) }
270      }
271    }
272
273    impl AsMut<[$rust_type]> for $name {
274      fn as_mut(&mut self) -> &mut [$rust_type] {
275        unsafe { std::slice::from_raw_parts_mut(self.data, self.length) }
276      }
277    }
278
279    impl TypeName for $name {
280      fn type_name() -> &'static str {
281        concat!("TypedArray<", stringify!($rust_type), ">")
282      }
283
284      fn value_type() -> crate::ValueType {
285        crate::ValueType::Object
286      }
287    }
288
289    impl ValidateNapiValue for $name {
290      unsafe fn validate(
291        env: sys::napi_env,
292        napi_val: sys::napi_value,
293      ) -> Result<crate::sys::napi_value> {
294        let mut is_typed_array = false;
295        check_status!(
296          unsafe { sys::napi_is_typedarray(env, napi_val, &mut is_typed_array) },
297          "Failed to check if value is typed array"
298        )?;
299        if !is_typed_array {
300          return Err(Error::new(
301            Status::InvalidArg,
302            "Expected a TypedArray value".to_owned(),
303          ));
304        }
305        Ok(ptr::null_mut())
306      }
307    }
308
309    impl FromNapiValue for $name {
310      unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
311        let mut typed_array_type = 0;
312        let mut length = 0;
313        let mut data = ptr::null_mut();
314        let mut array_buffer = ptr::null_mut();
315        let mut byte_offset = 0;
316        let mut ref_ = ptr::null_mut();
317        check_status!(
318          unsafe { sys::napi_create_reference(env, napi_val, 1, &mut ref_) },
319          "Failed to create reference from Buffer"
320        )?;
321        check_status!(
322          unsafe {
323            sys::napi_get_typedarray_info(
324              env,
325              napi_val,
326              &mut typed_array_type,
327              &mut length,
328              &mut data,
329              &mut array_buffer,
330              &mut byte_offset,
331            )
332          },
333          "Get TypedArray info failed"
334        )?;
335        if typed_array_type != $typed_array_type as i32 {
336          return Err(Error::new(
337            Status::InvalidArg,
338            format!("Expected $name, got {}", typed_array_type),
339          ));
340        }
341        Ok($name {
342          data: data as *mut $rust_type,
343          length,
344          byte_offset,
345          raw: Some((ref_, env)),
346          drop_in_vm: Arc::new(AtomicBool::new(true)),
347          data_managed_type: DataManagedType::Vm,
348          finalizer_notify: Box::into_raw(Box::new(Self::noop_finalize)),
349        })
350      }
351    }
352
353    impl ToNapiValue for $name {
354      unsafe fn to_napi_value(env: sys::napi_env, mut val: Self) -> Result<sys::napi_value> {
355        if let Some((ref_, _)) = val.raw {
356          let mut napi_value = std::ptr::null_mut();
357          check_status!(
358            unsafe { sys::napi_get_reference_value(env, ref_, &mut napi_value) },
359            "Failed to get reference from ArrayBuffer"
360          )?;
361          // fast path for ArrayBuffer::drop
362          if Arc::strong_count(&val.drop_in_vm) == 1 {
363            check_status!(
364              unsafe { sys::napi_delete_reference(env, ref_) },
365              "Failed to delete reference in ArrayBuffer::to_napi_value"
366            )?;
367            val.raw = Some((ptr::null_mut(), ptr::null_mut()));
368          }
369          return Ok(napi_value);
370        }
371        let mut arraybuffer_value = ptr::null_mut();
372        let ratio = mem::size_of::<$rust_type>();
373        let val_length = val.length;
374        let length = val_length * ratio;
375        let val_data = val.data;
376        val.drop_in_vm.store(true, Ordering::Release);
377        check_status!(
378          if length == 0 {
379            // Rust uses 0x1 as the data pointer for empty buffers,
380            // but NAPI/V8 only allows multiple buffers to have
381            // the same data pointer if it's 0x0.
382            unsafe {
383              sys::napi_create_arraybuffer(env, length, ptr::null_mut(), &mut arraybuffer_value)
384            }
385          } else {
386            let hint_ptr = Box::into_raw(Box::new(val));
387            let status = unsafe {
388              sys::napi_create_external_arraybuffer(
389                env,
390                val_data.cast(),
391                length,
392                Some(finalizer::<$rust_type, $name>),
393                hint_ptr.cast(),
394                &mut arraybuffer_value,
395              )
396            };
397            if status == napi_sys::Status::napi_no_external_buffers_allowed {
398              let hint = unsafe { Box::from_raw(hint_ptr) };
399              let mut underlying_data = ptr::null_mut();
400              let status = unsafe {
401                sys::napi_create_arraybuffer(
402                  env,
403                  length,
404                  &mut underlying_data,
405                  &mut arraybuffer_value,
406                )
407              };
408              unsafe { std::ptr::copy_nonoverlapping(hint.data.cast(), underlying_data, length) };
409              status
410            } else {
411              status
412            }
413          },
414          "Create external arraybuffer failed"
415        )?;
416        let mut napi_val = ptr::null_mut();
417        check_status!(
418          unsafe {
419            sys::napi_create_typedarray(
420              env,
421              $typed_array_type as i32,
422              val_length,
423              arraybuffer_value,
424              0,
425              &mut napi_val,
426            )
427          },
428          "Create TypedArray failed"
429        )?;
430        Ok(napi_val)
431      }
432    }
433
434    impl ToNapiValue for &mut $name {
435      unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
436        if let Some((ref_, _)) = val.raw {
437          let mut napi_value = std::ptr::null_mut();
438          check_status!(
439            unsafe { sys::napi_get_reference_value(env, ref_, &mut napi_value) },
440            "Failed to get reference from ArrayBuffer"
441          )?;
442          Ok(napi_value)
443        } else {
444          let cloned_value = $name {
445            drop_in_vm: val.drop_in_vm.clone(),
446            data: val.data,
447            length: val.length,
448            data_managed_type: val.data_managed_type,
449            finalizer_notify: Box::into_raw(Box::new($name::noop_finalize)),
450            raw: None,
451            byte_offset: val.byte_offset,
452          };
453          unsafe { ToNapiValue::to_napi_value(env, cloned_value) }
454        }
455      }
456    }
457  };
458}
459
460macro_rules! impl_from_slice {
461  ($name:ident, $rust_type:ident, $typed_array_type:expr) => {
462    impl FromNapiValue for &mut [$rust_type] {
463      unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
464        let mut typed_array_type = 0;
465        let mut length = 0;
466        let mut data = ptr::null_mut();
467        let mut array_buffer = ptr::null_mut();
468        let mut byte_offset = 0;
469        check_status!(
470          unsafe {
471            sys::napi_get_typedarray_info(
472              env,
473              napi_val,
474              &mut typed_array_type,
475              &mut length,
476              &mut data,
477              &mut array_buffer,
478              &mut byte_offset,
479            )
480          },
481          "Get TypedArray info failed"
482        )?;
483        if typed_array_type != $typed_array_type as i32 {
484          return Err(Error::new(
485            Status::InvalidArg,
486            format!("Expected $name, got {}", typed_array_type),
487          ));
488        }
489        Ok(if length == 0 {
490          &mut []
491        } else {
492          unsafe { core::slice::from_raw_parts_mut(data as *mut $rust_type, length) }
493        })
494      }
495    }
496
497    impl FromNapiValue for &[$rust_type] {
498      unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
499        let mut typed_array_type = 0;
500        let mut length = 0;
501        let mut data = ptr::null_mut();
502        let mut array_buffer = ptr::null_mut();
503        let mut byte_offset = 0;
504        check_status!(
505          unsafe {
506            sys::napi_get_typedarray_info(
507              env,
508              napi_val,
509              &mut typed_array_type,
510              &mut length,
511              &mut data,
512              &mut array_buffer,
513              &mut byte_offset,
514            )
515          },
516          "Get TypedArray info failed"
517        )?;
518        if typed_array_type != $typed_array_type as i32 {
519          return Err(Error::new(
520            Status::InvalidArg,
521            format!("Expected $name, got {}", typed_array_type),
522          ));
523        }
524        Ok(if length == 0 {
525          &[]
526        } else {
527          unsafe { core::slice::from_raw_parts_mut(data as *mut $rust_type, length) }
528        })
529      }
530    }
531
532    impl TypeName for &mut [$rust_type] {
533      fn type_name() -> &'static str {
534        concat!("TypedArray<", stringify!($rust_type), ">")
535      }
536
537      fn value_type() -> crate::ValueType {
538        crate::ValueType::Object
539      }
540    }
541
542    impl TypeName for &[$rust_type] {
543      fn type_name() -> &'static str {
544        concat!("TypedArray<", stringify!($rust_type), ">")
545      }
546
547      fn value_type() -> crate::ValueType {
548        crate::ValueType::Object
549      }
550    }
551
552    impl ValidateNapiValue for &[$rust_type] {
553      unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
554        let mut is_typed_array = false;
555        check_status!(
556          unsafe { sys::napi_is_typedarray(env, napi_val, &mut is_typed_array) },
557          "Failed to validate napi typed array"
558        )?;
559        if !is_typed_array {
560          return Err(Error::new(
561            Status::InvalidArg,
562            "Expected a TypedArray value".to_owned(),
563          ));
564        }
565        Ok(ptr::null_mut())
566      }
567    }
568
569    impl ValidateNapiValue for &mut [$rust_type] {
570      unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
571        let mut is_typed_array = false;
572        check_status!(
573          unsafe { sys::napi_is_typedarray(env, napi_val, &mut is_typed_array) },
574          "Failed to validate napi typed array"
575        )?;
576        if !is_typed_array {
577          return Err(Error::new(
578            Status::InvalidArg,
579            "Expected a TypedArray value".to_owned(),
580          ));
581        }
582        Ok(ptr::null_mut())
583      }
584    }
585  };
586}
587
588unsafe extern "C" fn finalizer<Data, T: Finalizer<RustType = Data>>(
589  _env: sys::napi_env,
590  finalize_data: *mut c_void,
591  finalize_hint: *mut c_void,
592) {
593  let data = unsafe { *Box::from_raw(finalize_hint as *mut T) };
594  let data_managed_type = *data.data_managed_type();
595  let length = *data.len();
596  match data_managed_type {
597    DataManagedType::Vm => {
598      // do nothing
599    }
600    DataManagedType::Owned => {
601      if data.ref_count() == 1 {
602        unsafe { Vec::from_raw_parts(finalize_data as *mut Data, length, length) };
603      }
604    }
605    DataManagedType::External => {
606      if data.ref_count() == 1 {
607        let finalizer_notify = unsafe { Box::from_raw(data.finalizer_notify()) };
608        (finalizer_notify)(finalize_data as *mut Data, length);
609      }
610    }
611  }
612}
613
614#[derive(PartialEq, Eq, Clone, Copy)]
615enum DataManagedType {
616  /// Vm managed data, passed in from JavaScript
617  Vm,
618  /// Rust owned data, which need to be deallocated in the finalizer
619  Owned,
620  /// External data, which need to be notice to the owner in finalizer
621  External,
622}
623
624impl_typed_array!(Int8Array, i8, TypedArrayType::Int8);
625impl_from_slice!(Int8Array, i8, TypedArrayType::Int8);
626impl_typed_array!(Uint8Array, u8, TypedArrayType::Uint8);
627impl_from_slice!(Uint8Array, u8, TypedArrayType::Uint8);
628impl_typed_array!(Uint8ClampedArray, u8, TypedArrayType::Uint8Clamped);
629impl_typed_array!(Int16Array, i16, TypedArrayType::Int16);
630impl_from_slice!(Int16Array, i16, TypedArrayType::Int16);
631impl_typed_array!(Uint16Array, u16, TypedArrayType::Uint16);
632impl_from_slice!(Uint16Array, u16, TypedArrayType::Uint16);
633impl_typed_array!(Int32Array, i32, TypedArrayType::Int32);
634impl_from_slice!(Int32Array, i32, TypedArrayType::Int32);
635impl_typed_array!(Uint32Array, u32, TypedArrayType::Uint32);
636impl_from_slice!(Uint32Array, u32, TypedArrayType::Uint32);
637impl_typed_array!(Float32Array, f32, TypedArrayType::Float32);
638impl_from_slice!(Float32Array, f32, TypedArrayType::Float32);
639impl_typed_array!(Float64Array, f64, TypedArrayType::Float64);
640impl_from_slice!(Float64Array, f64, TypedArrayType::Float64);
641#[cfg(feature = "napi6")]
642impl_typed_array!(BigInt64Array, i64, TypedArrayType::BigInt64);
643#[cfg(feature = "napi6")]
644impl_from_slice!(BigInt64Array, i64, TypedArrayType::BigInt64);
645#[cfg(feature = "napi6")]
646impl_typed_array!(BigUint64Array, u64, TypedArrayType::BigUint64);
647#[cfg(feature = "napi6")]
648impl_from_slice!(BigUint64Array, u64, TypedArrayType::BigUint64);
649
650/// Zero copy Uint8ClampedArray slice shared between Rust and Node.js.
651/// It can only be used in non-async context and the lifetime is bound to the fn closure.
652/// If you want to use Node.js `Uint8ClampedArray` in async context or want to extend the lifetime, use `Uint8ClampedArray` instead.
653pub struct Uint8ClampedSlice<'scope> {
654  pub(crate) inner: &'scope mut [u8],
655  raw_value: sys::napi_value,
656}
657
658impl<'scope> FromNapiValue for Uint8ClampedSlice<'scope> {
659  unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
660    let mut typed_array_type = 0;
661    let mut length = 0;
662    let mut data = ptr::null_mut();
663    let mut array_buffer = ptr::null_mut();
664    let mut byte_offset = 0;
665    check_status!(
666      unsafe {
667        sys::napi_get_typedarray_info(
668          env,
669          napi_val,
670          &mut typed_array_type,
671          &mut length,
672          &mut data,
673          &mut array_buffer,
674          &mut byte_offset,
675        )
676      },
677      "Get TypedArray info failed"
678    )?;
679    if typed_array_type != TypedArrayType::Uint8Clamped as i32 {
680      return Err(Error::new(
681        Status::InvalidArg,
682        format!("Expected $name, got {}", typed_array_type),
683      ));
684    }
685    Ok(Self {
686      inner: if length == 0 {
687        &mut []
688      } else {
689        unsafe { core::slice::from_raw_parts_mut(data.cast(), length) }
690      },
691      raw_value: napi_val,
692    })
693  }
694}
695
696impl ToNapiValue for Uint8ClampedSlice<'_> {
697  #[allow(unused_variables)]
698  unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
699    Ok(val.raw_value)
700  }
701}
702
703impl TypeName for Uint8ClampedSlice<'_> {
704  fn type_name() -> &'static str {
705    "Uint8ClampedArray"
706  }
707
708  fn value_type() -> ValueType {
709    ValueType::Object
710  }
711}
712
713impl ValidateNapiValue for Uint8ClampedSlice<'_> {
714  unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
715    let mut is_typedarray = false;
716    check_status!(
717      unsafe { sys::napi_is_typedarray(env, napi_val, &mut is_typedarray) },
718      "Failed to validate typed buffer"
719    )?;
720    if !is_typedarray {
721      return Err(Error::new(
722        Status::InvalidArg,
723        "Expected a TypedArray value".to_owned(),
724      ));
725    }
726    Ok(ptr::null_mut())
727  }
728}
729
730impl AsRef<[u8]> for Uint8ClampedSlice<'_> {
731  fn as_ref(&self) -> &[u8] {
732    self.inner
733  }
734}
735
736impl<'scope> Deref for Uint8ClampedSlice<'scope> {
737  type Target = [u8];
738
739  fn deref(&self) -> &Self::Target {
740    self.inner
741  }
742}
743
744impl<'scope> DerefMut for Uint8ClampedSlice<'scope> {
745  fn deref_mut(&mut self) -> &mut Self::Target {
746    self.inner
747  }
748}
749
750impl<T: Into<Vec<u8>>> From<T> for Uint8Array {
751  fn from(data: T) -> Self {
752    Uint8Array::new(data.into())
753  }
754}
755
756impl<T: Into<Vec<u8>>> From<T> for Uint8ClampedArray {
757  fn from(data: T) -> Self {
758    Uint8ClampedArray::new(data.into())
759  }
760}
761
762impl<T: Into<Vec<u16>>> From<T> for Uint16Array {
763  fn from(data: T) -> Self {
764    Uint16Array::new(data.into())
765  }
766}
767
768impl<T: Into<Vec<u32>>> From<T> for Uint32Array {
769  fn from(data: T) -> Self {
770    Uint32Array::new(data.into())
771  }
772}
773
774impl<T: Into<Vec<i8>>> From<T> for Int8Array {
775  fn from(data: T) -> Self {
776    Int8Array::new(data.into())
777  }
778}
779
780impl<T: Into<Vec<i16>>> From<T> for Int16Array {
781  fn from(data: T) -> Self {
782    Int16Array::new(data.into())
783  }
784}
785
786impl<T: Into<Vec<i32>>> From<T> for Int32Array {
787  fn from(data: T) -> Self {
788    Int32Array::new(data.into())
789  }
790}
791
792impl<T: Into<Vec<f32>>> From<T> for Float32Array {
793  fn from(data: T) -> Self {
794    Float32Array::new(data.into())
795  }
796}
797
798impl<T: Into<Vec<f64>>> From<T> for Float64Array {
799  fn from(data: T) -> Self {
800    Float64Array::new(data.into())
801  }
802}
803
804#[cfg(feature = "napi6")]
805impl<T: Into<Vec<i64>>> From<T> for BigInt64Array {
806  fn from(data: T) -> Self {
807    BigInt64Array::new(data.into())
808  }
809}
810#[cfg(feature = "napi6")]
811impl<T: Into<Vec<u64>>> From<T> for BigUint64Array {
812  fn from(data: T) -> Self {
813    BigUint64Array::new(data.into())
814  }
815}