napi_calm_down/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) && !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 = unsafe { *Box::from_raw(finalize_hint as *mut T) };
602  let data_managed_type = *data.data_managed_type();
603  let length = *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(finalize_data as *mut Data, length, length) };
611      }
612    }
613    DataManagedType::External => {
614      if data.ref_count() == 1 {
615        let finalizer_notify = 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 = 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        "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}