Skip to main content

napi/bindgen_runtime/js_values/
arraybuffer.rs

1use std::ffi::{c_void, CString};
2use std::marker::PhantomData;
3use std::mem;
4use std::ops::Deref;
5use std::ptr::{self, NonNull};
6
7#[cfg(all(feature = "napi4", not(feature = "noop")))]
8use crate::bindgen_prelude::{
9  current_custom_gc_handle, current_thread_owns_custom_gc, CustomGcHandle,
10};
11use crate::{
12  bindgen_prelude::{
13    FromNapiValue, JsObjectValue, JsValue, This, ToNapiValue, TypeName, ValidateNapiValue,
14  },
15  check_status, sys, Env, Error, Result, Status, Value, ValueType,
16};
17
18#[repr(i32)]
19#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
20#[non_exhaustive]
21pub enum TypedArrayType {
22  Int8 = 0,
23  Uint8,
24  Uint8Clamped,
25  Int16,
26  Uint16,
27  Int32,
28  Uint32,
29  Float32,
30  Float64,
31  #[cfg(feature = "napi6")]
32  BigInt64,
33  #[cfg(feature = "napi6")]
34  BigUint64,
35
36  /// compatible with higher versions
37  Unknown = 1024,
38}
39
40impl AsRef<str> for TypedArrayType {
41  fn as_ref(&self) -> &str {
42    match self {
43      TypedArrayType::Int8 => "Int8",
44      TypedArrayType::Uint8 => "Uint8",
45      TypedArrayType::Uint8Clamped => "Uint8Clamped",
46      TypedArrayType::Int16 => "Int16",
47      TypedArrayType::Uint16 => "Uint16",
48      TypedArrayType::Int32 => "Int32",
49      TypedArrayType::Uint32 => "Uint32",
50      TypedArrayType::Float32 => "Float32",
51      TypedArrayType::Float64 => "Float64",
52      #[cfg(feature = "napi6")]
53      TypedArrayType::BigInt64 => "BigInt64",
54      #[cfg(feature = "napi6")]
55      TypedArrayType::BigUint64 => "BigUint64",
56      TypedArrayType::Unknown => "Unknown",
57    }
58  }
59}
60
61impl From<sys::napi_typedarray_type> for TypedArrayType {
62  fn from(value: sys::napi_typedarray_type) -> Self {
63    match value {
64      sys::TypedarrayType::int8_array => Self::Int8,
65      sys::TypedarrayType::uint8_array => Self::Uint8,
66      sys::TypedarrayType::uint8_clamped_array => Self::Uint8Clamped,
67      sys::TypedarrayType::int16_array => Self::Int16,
68      sys::TypedarrayType::uint16_array => Self::Uint16,
69      sys::TypedarrayType::int32_array => Self::Int32,
70      sys::TypedarrayType::uint32_array => Self::Uint32,
71      sys::TypedarrayType::float32_array => Self::Float32,
72      sys::TypedarrayType::float64_array => Self::Float64,
73      #[cfg(feature = "napi6")]
74      sys::TypedarrayType::bigint64_array => Self::BigInt64,
75      #[cfg(feature = "napi6")]
76      sys::TypedarrayType::biguint64_array => Self::BigUint64,
77      _ => Self::Unknown,
78    }
79  }
80}
81
82impl From<TypedArrayType> for sys::napi_typedarray_type {
83  fn from(value: TypedArrayType) -> sys::napi_typedarray_type {
84    value as i32
85  }
86}
87
88#[cfg(target_family = "wasm")]
89extern "C" {
90  fn emnapi_sync_memory(
91    env: crate::sys::napi_env,
92    js_to_wasm: bool,
93    arraybuffer_or_view: crate::sys::napi_value,
94    byte_offset: usize,
95    length: usize,
96  ) -> crate::sys::napi_status;
97}
98
99#[derive(Clone, Copy)]
100/// Represents a JavaScript ArrayBuffer
101pub struct ArrayBuffer<'env> {
102  pub(crate) value: Value,
103  pub(crate) data: &'env [u8],
104}
105
106impl<'env> JsValue<'env> for ArrayBuffer<'env> {
107  fn value(&self) -> Value {
108    self.value
109  }
110}
111
112impl<'env> JsObjectValue<'env> for ArrayBuffer<'env> {}
113
114impl TypeName for ArrayBuffer<'_> {
115  fn type_name() -> &'static str {
116    "ArrayBuffer"
117  }
118
119  fn value_type() -> ValueType {
120    ValueType::Object
121  }
122}
123
124impl FromNapiValue for ArrayBuffer<'_> {
125  unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
126    let value = Value {
127      env,
128      value: napi_val,
129      value_type: ValueType::Object,
130    };
131    let mut data = ptr::null_mut();
132    let mut byte_length = 0;
133    check_status!(unsafe {
134      sys::napi_get_arraybuffer_info(env, napi_val, &mut data, &mut byte_length)
135    })?;
136    Ok(ArrayBuffer {
137      value,
138      data: if data.is_null() {
139        &[]
140      } else {
141        unsafe { std::slice::from_raw_parts(data as *const u8, byte_length) }
142      },
143    })
144  }
145}
146
147impl Deref for ArrayBuffer<'_> {
148  type Target = [u8];
149
150  fn deref(&self) -> &Self::Target {
151    self.data
152  }
153}
154
155impl<'env> ArrayBuffer<'env> {
156  /// Create a new `ArrayBuffer` from a `Vec<u8>`.
157  pub fn from_data<D: Into<Vec<u8>>>(env: &Env, data: D) -> Result<Self> {
158    let mut buf = ptr::null_mut();
159    let mut data = data.into();
160    let mut inner_ptr = data.as_mut_ptr();
161    #[cfg(all(debug_assertions, not(windows), not(target_family = "wasm")))]
162    {
163      let is_existed = super::BUFFER_DATA.with(|buffer_data| {
164        let buffer = buffer_data.lock().expect("Unlock buffer data failed");
165        buffer.contains(&inner_ptr)
166      });
167      if is_existed {
168        panic!("Share the same data between different buffers is not allowed, see: https://github.com/nodejs/node/issues/32463#issuecomment-631974747");
169      }
170    }
171    let len = data.len();
172    let cap = data.capacity();
173    let finalize_hint = Box::into_raw(Box::new((len, cap)));
174    let mut status = unsafe {
175      sys::napi_create_external_arraybuffer(
176        env.0,
177        inner_ptr.cast(),
178        data.len(),
179        Some(finalize_slice::<u8>),
180        finalize_hint.cast(),
181        &mut buf,
182      )
183    };
184    if status == napi_sys::Status::napi_no_external_buffers_allowed {
185      unsafe {
186        let _ = Box::from_raw(finalize_hint);
187      }
188      let mut underlying_data = ptr::null_mut();
189      status =
190        unsafe { sys::napi_create_arraybuffer(env.0, data.len(), &mut underlying_data, &mut buf) };
191      check_status!(status, "Failed to create arraybuffer")?;
192      if len > 0 {
193        let underlying_slice: &mut [u8] =
194          unsafe { std::slice::from_raw_parts_mut(underlying_data.cast(), len) };
195        underlying_slice.copy_from_slice(data.as_slice());
196      }
197      inner_ptr = underlying_data.cast();
198    } else {
199      check_status!(status, "Failed to create arraybuffer")?;
200      mem::forget(data);
201    }
202    Ok(Self {
203      value: Value {
204        env: env.0,
205        value: buf,
206        value_type: ValueType::Object,
207      },
208      data: if len == 0 {
209        &[]
210      } else {
211        unsafe { std::slice::from_raw_parts(inner_ptr.cast(), len) }
212      },
213    })
214  }
215
216  /// Mostly the same with `from_data`
217  ///
218  /// Provided `finalize_callback` will be called when `[u8]` got dropped.
219  /// You can pass in `noop_finalize` if you have nothing to do in finalize phase.
220  ///
221  /// ## Safety
222  ///
223  /// The caller must ensure that:
224  /// - The data pointer is valid for the lifetime of the buffer and points to a memory region of at least `len` bytes
225  /// - The finalize callback properly cleans up the data
226  ///
227  /// ### Notes
228  ///
229  /// JavaScript may mutate the data passed in to this buffer when writing the buffer.
230  /// However, some JavaScript runtimes do not support external buffers (notably electron!)
231  /// in which case modifications may be lost.
232  ///
233  /// If you need to support these runtimes, you should create a buffer by other means and then
234  /// later copy the data back out.
235  pub unsafe fn from_external<T: 'env, F: FnOnce(Env, T)>(
236    env: &Env,
237    data: *mut u8,
238    len: usize,
239    finalize_hint: T,
240    finalize_callback: F,
241  ) -> Result<Self> {
242    if data.is_null() || std::ptr::eq(data, crate::EMPTY_VEC.as_ptr()) {
243      return Err(Error::new(
244        Status::InvalidArg,
245        "Borrowed data should not be null".to_owned(),
246      ));
247    }
248    #[cfg(all(debug_assertions, not(windows), not(target_family = "wasm")))]
249    {
250      let is_existed = super::BUFFER_DATA.with(|buffer_data| {
251        let buffer = buffer_data.lock().expect("Unlock buffer data failed");
252        buffer.contains(&data)
253      });
254      if is_existed {
255        panic!("Share the same data between different buffers is not allowed, see: https://github.com/nodejs/node/issues/32463#issuecomment-631974747");
256      }
257    }
258    let hint_ptr = Box::into_raw(Box::new((finalize_hint, finalize_callback)));
259    let mut arraybuffer_value = ptr::null_mut();
260    let mut status = unsafe {
261      sys::napi_create_external_arraybuffer(
262        env.0,
263        data.cast(),
264        len,
265        Some(crate::env::raw_finalize_with_custom_callback::<T, F>),
266        hint_ptr.cast(),
267        &mut arraybuffer_value,
268      )
269    };
270    // `finalize` below reclaims `data`; on the copy fallback the slice must
271    // point at the engine-owned copy instead.
272    let mut data_ptr = data;
273    if status == sys::Status::napi_no_external_buffers_allowed {
274      let (hint, finalize) = *Box::from_raw(hint_ptr);
275      let mut underlying_data = ptr::null_mut();
276      status = unsafe {
277        sys::napi_create_arraybuffer(env.0, len, &mut underlying_data, &mut arraybuffer_value)
278      };
279      // Copy data before calling finalize, since finalize may free the source data
280      if status == sys::Status::napi_ok && len > 0 {
281        unsafe { std::ptr::copy_nonoverlapping(data.cast(), underlying_data, len) };
282      }
283      // Always call finalize to clean up caller's resources, even on error
284      finalize(*env, hint);
285      check_status!(status, "Failed to create arraybuffer from data")?;
286      data_ptr = underlying_data.cast();
287    } else {
288      check_status!(status, "Failed to create arraybuffer from data")?;
289    }
290
291    Ok(Self {
292      value: Value {
293        env: env.0,
294        value: arraybuffer_value,
295        value_type: ValueType::Object,
296      },
297      data: if len == 0 {
298        &[]
299      } else {
300        unsafe { std::slice::from_raw_parts(data_ptr, len) }
301      },
302    })
303  }
304
305  /// Copy data from a `&[u8]` and create a `ArrayBuffer` from it.
306  pub fn copy_from<D: AsRef<[u8]>>(env: &Env, data: D) -> Result<Self> {
307    let data = data.as_ref();
308    let len = data.len();
309    let mut arraybuffer_value = ptr::null_mut();
310    let mut underlying_data = ptr::null_mut();
311
312    check_status!(
313      unsafe {
314        sys::napi_create_arraybuffer(env.0, len, &mut underlying_data, &mut arraybuffer_value)
315      },
316      "Failed to create ArrayBuffer"
317    )?;
318
319    Ok(Self {
320      value: Value {
321        env: env.0,
322        value: arraybuffer_value,
323        value_type: ValueType::Object,
324      },
325      data: if len == 0 {
326        &[]
327      } else {
328        unsafe { std::slice::from_raw_parts(underlying_data.cast(), len) }
329      },
330    })
331  }
332
333  #[cfg(feature = "napi7")]
334  /// Generally, an ArrayBuffer is non-detachable if it has been detached before.
335  ///
336  /// The engine may impose additional conditions on whether an ArrayBuffer is detachable.
337  ///
338  /// For example, V8 requires that the ArrayBuffer be external, that is, created with napi_create_external_arraybuffer
339  pub fn detach(self) -> Result<()> {
340    check_status!(unsafe { sys::napi_detach_arraybuffer(self.value.env, self.value.value) })
341  }
342
343  #[cfg(feature = "napi7")]
344  /// The ArrayBuffer is considered `detached` if its internal data is null.
345  ///
346  /// This API represents the invocation of the `ArrayBuffer` `IsDetachedBuffer` operation as defined in [Section 24.1.1.2](https://tc39.es/ecma262/#sec-isdetachedbuffer) of the ECMAScript Language Specification.
347  pub fn is_detached(&self) -> Result<bool> {
348    let mut is_detached = false;
349    check_status!(unsafe {
350      sys::napi_is_detached_arraybuffer(self.value.env, self.value.value, &mut is_detached)
351    })?;
352    Ok(is_detached)
353  }
354
355  /// # Safety
356  ///
357  /// This is literally undefined behavior, as the JS side may always modify the underlying buffer,
358  /// without synchronization.
359  pub unsafe fn as_mut(&mut self) -> &mut [u8] {
360    std::slice::from_raw_parts_mut(self.data.as_ptr() as *mut u8, self.data.len())
361  }
362}
363
364#[derive(Clone, Copy)]
365/// Represents a JavaScript ArrayBuffer
366pub struct TypedArray<'env> {
367  pub(crate) value: Value,
368  pub typed_array_type: TypedArrayType,
369  pub arraybuffer: ArrayBuffer<'env>,
370  pub byte_offset: usize,
371}
372
373impl TypeName for TypedArray<'_> {
374  fn type_name() -> &'static str {
375    "TypedArray"
376  }
377
378  fn value_type() -> ValueType {
379    ValueType::Object
380  }
381}
382
383impl ValidateNapiValue for TypedArray<'_> {
384  unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
385    let mut is_typedarray = false;
386    check_status!(
387      unsafe { sys::napi_is_typedarray(env, napi_val, &mut is_typedarray) },
388      "Failed to validate TypedArray"
389    )?;
390    if !is_typedarray {
391      return Err(Error::new(
392        Status::InvalidArg,
393        "Value is not a TypedArray".to_owned(),
394      ));
395    }
396    Ok(ptr::null_mut())
397  }
398}
399
400impl<'env> JsValue<'env> for TypedArray<'env> {
401  fn value(&self) -> Value {
402    self.value
403  }
404}
405
406impl<'env> JsObjectValue<'env> for TypedArray<'env> {}
407
408impl FromNapiValue for TypedArray<'_> {
409  unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
410    let value = Value {
411      env,
412      value: napi_val,
413      value_type: ValueType::Object,
414    };
415    let mut typed_array_type = 0;
416    let mut data = ptr::null_mut();
417    let mut length = 0;
418    let mut arraybuffer = ptr::null_mut();
419    let mut byte_offset = 0;
420    check_status!(
421      unsafe {
422        sys::napi_get_typedarray_info(
423          env,
424          napi_val,
425          &mut typed_array_type,
426          &mut length,
427          &mut data,
428          &mut arraybuffer,
429          &mut byte_offset,
430        )
431      },
432      "Failed to get typedarray info"
433    )?;
434    Ok(Self {
435      value: Value {
436        env,
437        value: napi_val,
438        value_type: ValueType::Object,
439      },
440      typed_array_type: typed_array_type.into(),
441      byte_offset,
442      arraybuffer: ArrayBuffer {
443        value,
444        data: if data.is_null() {
445          &[]
446        } else {
447          unsafe { std::slice::from_raw_parts(data as *const u8, length) }
448        },
449      },
450    })
451  }
452}
453
454trait Finalizer {
455  type RustType;
456
457  fn finalizer_notify(&self) -> *mut dyn FnOnce(*mut Self::RustType, usize);
458}
459
460macro_rules! impl_typed_array {
461  ($name:ident, $rust_type:ident, $typed_array_type:expr) => {
462    pub struct $name {
463      data: *mut $rust_type,
464      length: usize,
465      capacity: usize,
466      #[allow(unused)]
467      byte_offset: usize,
468      raw: Option<(crate::sys::napi_ref, crate::sys::napi_env)>,
469      #[cfg(all(feature = "napi4", not(feature = "noop")))]
470      custom_gc_handle: Option<std::sync::Arc<CustomGcHandle>>,
471      finalizer_notify: *mut dyn FnOnce(*mut $rust_type, usize),
472    }
473
474    /// SAFETY: This is undefined behavior, as the JS side may always modify the underlying buffer,
475    /// without synchronization. Also see the docs for the `DerfMut` impl.
476    unsafe impl Send for $name {}
477    unsafe impl Sync for $name {}
478
479    impl Finalizer for $name {
480      type RustType = $rust_type;
481
482      fn finalizer_notify(&self) -> *mut dyn FnOnce(*mut Self::RustType, usize) {
483        self.finalizer_notify
484      }
485    }
486
487    impl Drop for $name {
488      fn drop(&mut self) {
489        if let Some((ref_, env)) = self.raw {
490          // If the ref is null, it means the TypedArray has been called `ToNapiValue::to_napi_value`, and the `ref` has been deleted
491          // If the env is null, it means the TypedArray is copied in `&mut TypedArray ToNapiValue::to_napi_value`, and the `ref` will be deleted in the raw TypedArray
492          if ref_.is_null() || env.is_null() {
493            return;
494          }
495          #[cfg(all(feature = "napi4", not(feature = "noop")))]
496          {
497            if let Some(handle) = self.custom_gc_handle.as_ref() {
498              handle.with_read_aborted(|aborted| {
499                if aborted {
500                  // owner env gone, V8 already invalidated the ref -> no-op (safe leak).
501                  // Reached on BOTH the off-thread AND the same-thread (cached-value-at-thread-exit) paths.
502                  return;
503                }
504                if current_thread_owns_custom_gc(handle) {
505                  // same isolate's JS thread, owner alive -> direct unref+delete on the OWNER env.
506                  // DELIBERATE copy of the trailing direct block below; the copy is `aborted`-gated, the
507                  // trailing block is the non-napi4 / None-handle fallback. Do NOT "dedupe" either away.
508                  let mut ref_count = 0;
509                  crate::check_status_or_throw!(
510                    env,
511                    unsafe { sys::napi_reference_unref(env, ref_, &mut ref_count) },
512                    "Failed to unref ArrayBuffer reference in drop"
513                  );
514                  debug_assert!(
515                    ref_count == 0,
516                    "ArrayBuffer reference count in ArrayBuffer::drop is not zero"
517                  );
518                  crate::check_status_or_throw!(
519                    env,
520                    unsafe { sys::napi_delete_reference(env, ref_) },
521                    "Failed to delete ArrayBuffer reference in drop"
522                  );
523                } else {
524                  // off-thread OR a different isolate's JS thread (fixes F5) -> route to ITS tsfn
525                  let status =
526                    unsafe { sys::napi_call_threadsafe_function(handle.get_raw(), ref_.cast(), 1) };
527                  assert!(
528                    status == sys::Status::napi_ok || status == sys::Status::napi_closing,
529                    "Call custom GC in ArrayBuffer::drop failed {}",
530                    Status::from(status)
531                  );
532                }
533              });
534              return;
535            }
536            // handle == None -> fall through (under napi4 this is practically unreachable
537            // for a ref-carrying value: since #3357 `create_custom_gc` installs the per-env
538            // handle BEFORE any module-init callback runs, so any value captured via
539            // FromNapiValue on a registered JS thread records a real handle, not None).
540          }
541          let mut ref_count = 0;
542          crate::check_status_or_throw!(
543            env,
544            unsafe { sys::napi_reference_unref(env, ref_, &mut ref_count) },
545            "Failed to unref ArrayBuffer reference in drop"
546          );
547          debug_assert!(
548            ref_count == 0,
549            "ArrayBuffer reference count in ArrayBuffer::drop is not zero"
550          );
551          crate::check_status_or_throw!(
552            env,
553            unsafe { sys::napi_delete_reference(env, ref_) },
554            "Failed to delete ArrayBuffer reference in drop"
555          );
556          return;
557        }
558        // If the `finalizer_notify` is not null, it means the data is external, and we call the finalizer instead of the `Vec::from_raw_parts`
559        if !self.finalizer_notify().is_null() {
560          let finalizer = unsafe { Box::from_raw(self.finalizer_notify) };
561          (finalizer)(self.data, self.length);
562          return;
563        }
564        if !self.data.is_null() {
565          unsafe { Vec::from_raw_parts(self.data, self.length, self.capacity) };
566        }
567      }
568    }
569
570    impl $name {
571      #[cfg(target_family = "wasm")]
572      pub fn sync(&mut self, env: &crate::Env) {
573        if let Some((reference, _)) = self.raw {
574          let mut value = ptr::null_mut();
575          let mut array_buffer = ptr::null_mut();
576          crate::check_status_or_throw!(
577            env.raw(),
578            unsafe { crate::sys::napi_get_reference_value(env.raw(), reference, &mut value) },
579            "Failed to get reference value from TypedArray while syncing"
580          );
581          crate::check_status_or_throw!(
582            env.raw(),
583            unsafe {
584              crate::sys::napi_get_typedarray_info(
585                env.raw(),
586                value,
587                &mut ($typed_array_type as i32) as *mut i32,
588                &mut self.length as *mut usize,
589                ptr::null_mut(),
590                &mut array_buffer,
591                &mut self.byte_offset as *mut usize,
592              )
593            },
594            "Failed to get ArrayBuffer under the TypedArray while syncing"
595          );
596          crate::check_status_or_throw!(
597            env.raw(),
598            unsafe {
599              emnapi_sync_memory(
600                env.raw(),
601                false,
602                array_buffer,
603                self.byte_offset,
604                self.length,
605              )
606            },
607            "Failed to sync memory"
608          );
609        } else {
610          return;
611        }
612      }
613
614      pub fn new(mut data: Vec<$rust_type>) -> Self {
615        data.shrink_to_fit();
616        let ret = $name {
617          data: data.as_mut_ptr(),
618          length: data.len(),
619          capacity: data.capacity(),
620          byte_offset: 0,
621          raw: None,
622          #[cfg(all(feature = "napi4", not(feature = "noop")))]
623          custom_gc_handle: None,
624          finalizer_notify: ptr::null_mut::<fn(*mut $rust_type, usize)>(),
625        };
626        mem::forget(data);
627        ret
628      }
629
630      pub fn with_data_copied<D>(data: D) -> Self
631      where
632        D: AsRef<[$rust_type]>,
633      {
634        let mut data_copied = data.as_ref().to_vec();
635        let ret = $name {
636          data: data_copied.as_mut_ptr(),
637          length: data.as_ref().len(),
638          capacity: data_copied.capacity(),
639          finalizer_notify: ptr::null_mut::<fn(*mut $rust_type, usize)>(),
640          raw: None,
641          #[cfg(all(feature = "napi4", not(feature = "noop")))]
642          custom_gc_handle: None,
643          byte_offset: 0,
644        };
645        mem::forget(data_copied);
646        ret
647      }
648
649      /// # Safety
650      ///
651      /// The caller will be notified when the data is deallocated by vm
652      pub unsafe fn with_external_data<F>(data: *mut $rust_type, length: usize, notify: F) -> Self
653      where
654        F: 'static + FnOnce(*mut $rust_type, usize),
655      {
656        $name {
657          data,
658          length,
659          capacity: length,
660          finalizer_notify: Box::into_raw(Box::new(notify)),
661          raw: None,
662          #[cfg(all(feature = "napi4", not(feature = "noop")))]
663          custom_gc_handle: None,
664          byte_offset: 0,
665        }
666      }
667
668      #[allow(clippy::should_implement_trait)]
669      /// # Safety
670      ///
671      /// This is literally undefined behavior, as the JS side may always modify the underlying buffer,
672      /// without synchronization.
673      pub unsafe fn as_mut(&mut self) -> &mut [$rust_type] {
674        if self.data.is_null() {
675          return &mut [];
676        }
677
678        unsafe { std::slice::from_raw_parts_mut(self.data, self.length) }
679      }
680    }
681
682    impl Deref for $name {
683      type Target = [$rust_type];
684
685      fn deref(&self) -> &Self::Target {
686        self.as_ref()
687      }
688    }
689
690    impl AsRef<[$rust_type]> for $name {
691      fn as_ref(&self) -> &[$rust_type] {
692        if self.data.is_null() {
693          return &[];
694        }
695
696        unsafe { std::slice::from_raw_parts(self.data, self.length) }
697      }
698    }
699
700    impl TypeName for $name {
701      fn type_name() -> &'static str {
702        concat!("TypedArray<", stringify!($rust_type), ">")
703      }
704
705      fn value_type() -> crate::ValueType {
706        crate::ValueType::Object
707      }
708    }
709
710    impl ValidateNapiValue for $name {
711      unsafe fn validate(
712        env: sys::napi_env,
713        napi_val: sys::napi_value,
714      ) -> Result<crate::sys::napi_value> {
715        let mut is_typed_array = false;
716        check_status!(
717          unsafe { sys::napi_is_typedarray(env, napi_val, &mut is_typed_array) },
718          "Failed to check if value is typed array"
719        )?;
720        if !is_typed_array {
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
730    impl FromNapiValue for $name {
731      unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
732        let mut typed_array_type = 0;
733        let mut length = 0;
734        let mut data = ptr::null_mut();
735        let mut array_buffer = ptr::null_mut();
736        let mut byte_offset = 0;
737        let mut ref_ = ptr::null_mut();
738        check_status!(
739          unsafe { sys::napi_create_reference(env, napi_val, 1, &mut ref_) },
740          "Failed to create reference from TypedArray"
741        )?;
742        check_status!(
743          unsafe {
744            sys::napi_get_typedarray_info(
745              env,
746              napi_val,
747              &mut typed_array_type,
748              &mut length,
749              &mut data,
750              &mut array_buffer,
751              &mut byte_offset,
752            )
753          },
754          "Get TypedArray info failed"
755        )?;
756        if typed_array_type != $typed_array_type as i32 {
757          return Err(Error::new(
758            Status::InvalidArg,
759            format!(
760              "Expected {}, got {}Array",
761              stringify!($name),
762              TypedArrayType::from(typed_array_type).as_ref()
763            ),
764          ));
765        }
766        Ok($name {
767          data: data.cast(),
768          length,
769          capacity: length,
770          byte_offset,
771          raw: Some((ref_, env)),
772          #[cfg(all(feature = "napi4", not(feature = "noop")))]
773          custom_gc_handle: current_custom_gc_handle(),
774          finalizer_notify: ptr::null_mut::<fn(*mut $rust_type, usize)>(),
775        })
776      }
777    }
778
779    impl ToNapiValue for $name {
780      unsafe fn to_napi_value(env: sys::napi_env, mut val: Self) -> Result<sys::napi_value> {
781        if let Some((ref_, _)) = val.raw {
782          let mut napi_value = std::ptr::null_mut();
783          check_status!(
784            unsafe { sys::napi_get_reference_value(env, ref_, &mut napi_value) },
785            "Failed to get reference from ArrayBuffer"
786          )?;
787          check_status!(
788            unsafe { sys::napi_delete_reference(env, ref_) },
789            "Failed to delete reference in ArrayBuffer::to_napi_value"
790          )?;
791          val.raw = Some((ptr::null_mut(), ptr::null_mut()));
792          return Ok(napi_value);
793        }
794        let mut arraybuffer_value = ptr::null_mut();
795        let ratio = mem::size_of::<$rust_type>();
796        let val_length = val.length;
797        let length = val_length * ratio;
798        let val_data = val.data;
799        if length == 0 {
800          // Rust uses 0x1 as the data pointer for empty buffers,
801          // but NAPI/V8 only allows multiple buffers to have
802          // the same data pointer if it's 0x0.
803          check_status!(
804            unsafe {
805              sys::napi_create_arraybuffer(env, length, ptr::null_mut(), &mut arraybuffer_value)
806            },
807            "Create external arraybuffer failed"
808          )?;
809        } else {
810          let hint_ptr = Box::into_raw(Box::new(val));
811          let mut status = unsafe {
812            sys::napi_create_external_arraybuffer(
813              env,
814              val_data.cast(),
815              length,
816              Some(finalizer::<$rust_type, $name>),
817              hint_ptr.cast(),
818              &mut arraybuffer_value,
819            )
820          };
821          if status == napi_sys::Status::napi_no_external_buffers_allowed {
822            let hint = unsafe { Box::from_raw(hint_ptr) };
823            let mut underlying_data = ptr::null_mut();
824            status = unsafe {
825              sys::napi_create_arraybuffer(
826                env,
827                length,
828                &mut underlying_data,
829                &mut arraybuffer_value,
830              )
831            };
832            check_status!(status, "Create external arraybuffer failed")?;
833            if length > 0 {
834              unsafe { std::ptr::copy_nonoverlapping(hint.data.cast(), underlying_data, length) };
835            }
836          } else {
837            check_status!(status, "Create external arraybuffer failed")?;
838          }
839        }
840        let mut napi_val = ptr::null_mut();
841        check_status!(
842          unsafe {
843            sys::napi_create_typedarray(
844              env,
845              $typed_array_type as i32,
846              val_length,
847              arraybuffer_value,
848              0,
849              &mut napi_val,
850            )
851          },
852          "Create TypedArray failed"
853        )?;
854        Ok(napi_val)
855      }
856    }
857
858    impl ToNapiValue for &mut $name {
859      unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
860        if let Some((ref_, _)) = val.raw {
861          let mut napi_value = std::ptr::null_mut();
862          check_status!(
863            unsafe { sys::napi_get_reference_value(env, ref_, &mut napi_value) },
864            "Failed to get reference from ArrayBuffer"
865          )?;
866          return Ok(napi_value);
867        }
868        let mut arraybuffer_value = ptr::null_mut();
869        let ratio = mem::size_of::<$rust_type>();
870        let val_length = val.length;
871        let length = val_length * ratio;
872        let val_data = val.data;
873        let mut copied_val = None;
874        if length == 0 {
875          // Rust uses 0x1 as the data pointer for empty buffers,
876          // but NAPI/V8 only allows multiple buffers to have
877          // the same data pointer if it's 0x0.
878          check_status!(
879            unsafe {
880              sys::napi_create_arraybuffer(env, length, ptr::null_mut(), &mut arraybuffer_value)
881            },
882            "Create external arraybuffer failed"
883          )?;
884        } else {
885          // manually copy the data instead of implement `Clone` & `Copy` for TypedArray
886          // the TypedArray can't be copied if raw is not None
887          let val_copy = $name {
888            data: val.data,
889            length: val.length,
890            capacity: val.capacity,
891            byte_offset: val.byte_offset,
892            raw: None,
893            #[cfg(all(feature = "napi4", not(feature = "noop")))]
894            custom_gc_handle: None,
895            finalizer_notify: val.finalizer_notify,
896          };
897          let hint_ref: &mut $name = Box::leak(Box::new(val_copy));
898          let hint_ptr = hint_ref as *mut $name;
899          copied_val = Some(hint_ref);
900          let mut status = unsafe {
901            sys::napi_create_external_arraybuffer(
902              env,
903              val_data.cast(),
904              length,
905              Some(finalizer::<$rust_type, $name>),
906              hint_ptr.cast(),
907              &mut arraybuffer_value,
908            )
909          };
910          if status == napi_sys::Status::napi_no_external_buffers_allowed {
911            let hint = unsafe { Box::from_raw(hint_ptr) };
912            // Reset copied_val since hint is being reclaimed and will be dropped
913            copied_val = None;
914            // Clear val's data fields IMMEDIATELY after reclaiming hint.
915            // hint now owns the data and will free it when dropped (including on early return).
916            // We must clear val's fields before any check_status! that could return early,
917            // otherwise val would have dangling pointers if we return with an error.
918            // Note: hint.data still has the valid pointer for the copy operation below.
919            val.data = ptr::null_mut();
920            val.length = 0;
921            val.capacity = 0;
922            val.finalizer_notify = ptr::null_mut::<fn(*mut $rust_type, usize)>();
923            let mut underlying_data = ptr::null_mut();
924            status = unsafe {
925              sys::napi_create_arraybuffer(
926                env,
927                length,
928                &mut underlying_data,
929                &mut arraybuffer_value,
930              )
931            };
932            check_status!(status, "Create external arraybuffer failed")?;
933            if length > 0 {
934              unsafe { std::ptr::copy_nonoverlapping(hint.data.cast(), underlying_data, length) };
935            }
936          } else {
937            check_status!(status, "Create external arraybuffer failed")?;
938          }
939        }
940        let mut napi_val = ptr::null_mut();
941        check_status!(
942          unsafe {
943            sys::napi_create_typedarray(
944              env,
945              $typed_array_type as i32,
946              val_length,
947              arraybuffer_value,
948              0,
949              &mut napi_val,
950            )
951          },
952          "Create TypedArray failed"
953        )?;
954        let mut ref_ = ptr::null_mut();
955        check_status!(
956          unsafe { sys::napi_create_reference(env, napi_val, 1, &mut ref_) },
957          "Failed to delete reference in ArrayBuffer::to_napi_value"
958        )?;
959        val.raw = Some((ref_, env));
960        #[cfg(all(feature = "napi4", not(feature = "noop")))]
961        {
962          val.custom_gc_handle = current_custom_gc_handle();
963        }
964        if let Some(copied_val) = copied_val {
965          val.finalizer_notify = ptr::null_mut::<fn(*mut $rust_type, usize)>();
966          val.data = ptr::null_mut();
967          val.length = 0;
968          val.capacity = 0;
969          copied_val.raw = Some((ref_, ptr::null_mut()));
970        }
971        Ok(napi_val)
972      }
973    }
974  };
975}
976
977macro_rules! impl_from_slice {
978  ($name:ident, $slice_type:ident, $rust_type:ident, $typed_array_type:expr) => {
979    #[derive(Clone, Copy)]
980    pub struct $slice_type<'env> {
981      pub(crate) inner: NonNull<$rust_type>,
982      pub(crate) length: usize,
983      raw_value: sys::napi_value,
984      env: sys::napi_env,
985      _marker: PhantomData<&'env ()>,
986    }
987
988    impl <'env> $slice_type<'env> {
989      #[doc = " Create a new `"]
990      #[doc = stringify!($slice_type)]
991      #[doc = "` from a `Vec<"]
992      #[doc = stringify!($rust_type)]
993      #[doc = ">`."]
994      pub fn from_data<D: Into<Vec<$rust_type>>>(env: &Env, data: D) -> Result<Self> {
995        let mut buf = ptr::null_mut();
996        let mut data = data.into();
997        let mut inner_ptr = data.as_mut_ptr();
998        #[cfg(all(debug_assertions, not(windows), not(target_family = "wasm")))]
999        {
1000          let is_existed = super::BUFFER_DATA.with(|buffer_data| {
1001            let buffer = buffer_data.lock().expect("Unlock buffer data failed");
1002            buffer.contains(&inner_ptr.cast())
1003          });
1004          if is_existed {
1005            panic!("Share the same data between different buffers is not allowed, see: https://github.com/nodejs/node/issues/32463#issuecomment-631974747");
1006          }
1007        }
1008        let len = data.len();
1009        let array_buffer_len = len * mem::size_of::<$rust_type>();
1010        let cap = data.capacity();
1011        let finalize_hint = Box::into_raw(Box::new((len, cap)));
1012        let mut status = unsafe {
1013          sys::napi_create_external_arraybuffer(
1014            env.0,
1015            inner_ptr.cast(),
1016            array_buffer_len,
1017            Some(finalize_slice::<$rust_type>),
1018            finalize_hint.cast(),
1019            &mut buf,
1020          )
1021        };
1022        if status == napi_sys::Status::napi_no_external_buffers_allowed {
1023          unsafe {
1024            let _ = Box::from_raw(finalize_hint);
1025          }
1026          let mut underlying_data = ptr::null_mut();
1027          status = unsafe {
1028            sys::napi_create_arraybuffer(
1029              env.0,
1030              array_buffer_len,
1031              &mut underlying_data,
1032              &mut buf,
1033            )
1034          };
1035          check_status!(status, "Failed to create buffer slice from data")?;
1036          if array_buffer_len > 0 {
1037            let underlying_slice: &mut [u8] =
1038              unsafe { std::slice::from_raw_parts_mut(underlying_data.cast(), array_buffer_len) };
1039            underlying_slice.copy_from_slice(unsafe { core::slice::from_raw_parts(inner_ptr.cast(), array_buffer_len) });
1040          }
1041          inner_ptr = underlying_data.cast();
1042        } else {
1043          check_status!(status, "Failed to create buffer slice from data")?;
1044          mem::forget(data);
1045        }
1046
1047        let mut napi_val = ptr::null_mut();
1048        check_status!(
1049          unsafe {
1050            sys::napi_create_typedarray(
1051              env.0,
1052              $typed_array_type as i32,
1053              len,
1054              buf,
1055              0,
1056              &mut napi_val,
1057            )
1058          },
1059          "Create TypedArray failed"
1060        )?;
1061
1062        Ok(Self {
1063          inner: if len == 0 {
1064            NonNull::dangling()
1065          } else {
1066            unsafe { NonNull::new_unchecked(inner_ptr.cast()) }
1067          },
1068          length: len,
1069          raw_value: napi_val,
1070          env: env.0,
1071          _marker: PhantomData,
1072        })
1073      }
1074
1075      #[doc = "Mostly the same with `from_data`"]
1076      #[doc = ""]
1077      #[doc = "Provided `finalize_callback` will be called when `"]
1078      #[doc = stringify!($slice_type)]
1079      #[doc = "` got dropped."]
1080      #[doc = "You can pass in `noop_finalize` if you have nothing to do in finalize phase."]
1081      #[doc = ""]
1082      #[doc = "## Safety"]
1083      #[doc = ""]
1084      #[doc = "The caller must ensure that:"]
1085      #[doc = "- The data pointer is valid for the lifetime of the buffer and points to a memory region of at least `len` elements"]
1086      #[doc = "- The finalize callback properly cleans up the data"]
1087      #[doc = ""]
1088      #[doc = "### Notes"]
1089      #[doc = ""]
1090      #[doc = "JavaScript may mutate the data passed in to this buffer when writing the buffer."]
1091      #[doc = "However, some JavaScript runtimes do not support external buffers (notably electron!)"]
1092      #[doc = "in which case modifications may be lost."]
1093      #[doc = ""]
1094      #[doc = "If you need to support these runtimes, you should create a buffer by other means and then"]
1095      #[doc = "later copy the data back out."]
1096      pub unsafe fn from_external<T: 'env, F: FnOnce(Env, T)>(
1097        env: &Env,
1098        data: *mut $rust_type,
1099        data_len: usize,
1100        finalize_hint: T,
1101        finalize_callback: F,
1102      ) -> Result<Self> {
1103        if data.is_null() || data as *const u8 == crate::EMPTY_VEC.as_ptr() {
1104          return Err(Error::new(
1105            Status::InvalidArg,
1106            "Borrowed data should not be null".to_owned(),
1107          ));
1108        }
1109        #[cfg(all(debug_assertions, not(windows), not(target_family = "wasm")))]
1110        {
1111          let is_existed = super::BUFFER_DATA.with(|buffer_data| {
1112            let buffer = buffer_data.lock().expect("Unlock buffer data failed");
1113            buffer.contains(&data.cast())
1114          });
1115          if is_existed {
1116            panic!("Share the same data between different buffers is not allowed, see: https://github.com/nodejs/node/issues/32463#issuecomment-631974747");
1117          }
1118        }
1119        let hint_ptr = Box::into_raw(Box::new((finalize_hint, finalize_callback)));
1120        let mut arraybuffer_value = ptr::null_mut();
1121        let array_buffer_len = data_len * mem::size_of::<$rust_type>();
1122        let mut status = unsafe {
1123          sys::napi_create_external_arraybuffer(
1124            env.0,
1125            data.cast(),
1126            array_buffer_len,
1127            Some(crate::env::raw_finalize_with_custom_callback::<T, F>),
1128            hint_ptr.cast(),
1129            &mut arraybuffer_value,
1130          )
1131        };
1132        // `finalize` below reclaims `data`; on the copy fallback `inner` must
1133        // point at the engine-owned copy instead.
1134        let mut inner_ptr: *mut $rust_type = data;
1135        if status == sys::Status::napi_no_external_buffers_allowed {
1136          let (hint, finalize) = *Box::from_raw(hint_ptr);
1137          let mut underlying_data = ptr::null_mut();
1138          status = unsafe {
1139            sys::napi_create_arraybuffer(
1140              env.0,
1141              array_buffer_len,
1142              &mut underlying_data,
1143              &mut arraybuffer_value,
1144            )
1145          };
1146          // Copy data before calling finalize, since finalize may free the source data
1147          if status == sys::Status::napi_ok && array_buffer_len > 0 {
1148            let underlying_slice: &mut [u8] =
1149              unsafe { std::slice::from_raw_parts_mut(underlying_data.cast(), array_buffer_len) };
1150            underlying_slice.copy_from_slice(unsafe { std::slice::from_raw_parts(data.cast(), array_buffer_len) });
1151          }
1152          // Always call finalize to clean up caller's resources, even on error
1153          finalize(*env, hint);
1154          check_status!(status, "Failed to create arraybuffer from data")?;
1155          inner_ptr = underlying_data.cast();
1156        } else {
1157          check_status!(status, "Failed to create arraybuffer from data")?;
1158        }
1159
1160        let mut napi_val = ptr::null_mut();
1161        check_status!(
1162          unsafe {
1163            sys::napi_create_typedarray(
1164              env.0,
1165              $typed_array_type as i32,
1166              data_len,
1167              arraybuffer_value,
1168              0,
1169              &mut napi_val,
1170            )
1171          },
1172          "Create TypedArray failed"
1173        )?;
1174
1175        Ok(Self {
1176          inner: if data_len == 0 {
1177            NonNull::dangling()
1178          } else {
1179            unsafe { NonNull::new_unchecked(inner_ptr) }
1180          },
1181          length: data_len,
1182          raw_value: napi_val,
1183          env: env.0,
1184          _marker: PhantomData,
1185        })
1186      }
1187
1188      #[doc = "Copy data from a `&["]
1189      #[doc = stringify!($rust_type)]
1190      #[doc = "]` and create a `"]
1191      #[doc = stringify!($slice_type)]
1192      #[doc = "` from it."]
1193      pub fn copy_from<D: AsRef<[$rust_type]>>(env: &Env, data: D) -> Result<Self> {
1194        let data = data.as_ref();
1195        let len = data.len();
1196        let mut arraybuffer_value = ptr::null_mut();
1197        let mut underlying_data = ptr::null_mut();
1198
1199        check_status!(
1200          unsafe {
1201            sys::napi_create_arraybuffer(
1202              env.0,
1203              len,
1204              &mut underlying_data,
1205              &mut arraybuffer_value,
1206            )
1207          },
1208          "Failed to create ArrayBuffer"
1209        )?;
1210
1211        let mut napi_val = ptr::null_mut();
1212        check_status!(
1213          unsafe {
1214            sys::napi_create_typedarray(
1215              env.0,
1216              $typed_array_type as i32,
1217              len,
1218              arraybuffer_value,
1219              0,
1220              &mut napi_val,
1221            )
1222          },
1223          "Create TypedArray failed"
1224        )?;
1225
1226        Ok(Self {
1227          inner: if len == 0 {
1228            NonNull::dangling()
1229          } else {
1230            unsafe { NonNull::new_unchecked(underlying_data.cast()) }
1231          },
1232          length: len,
1233          raw_value: napi_val,
1234          env: env.0,
1235          _marker: PhantomData,
1236        })
1237      }
1238
1239      /// Create from `ArrayBuffer`
1240      pub fn from_arraybuffer(arraybuffer: &ArrayBuffer<'env>, byte_offset: usize, length: usize) -> Result<$slice_type<'env>> {
1241        let env = arraybuffer.value.env;
1242        let mut typed_array = ptr::null_mut();
1243        check_status!(unsafe {
1244          sys::napi_create_typedarray(env, $typed_array_type.into(), length, arraybuffer.value().value, byte_offset, &mut typed_array)
1245        }, "Failed to create TypedArray from ArrayBuffer")?;
1246
1247        unsafe { FromNapiValue::from_napi_value(env, typed_array) }
1248      }
1249
1250      /// extends the lifetime of the `TypedArray` to the lifetime of the `This`
1251      pub fn assign_to_this<'a, U>(&self, this: This<'a, U>, name: &str) -> Result<$slice_type<'a>>
1252      where
1253        U: FromNapiValue + JsObjectValue<'a>,
1254      {
1255        let name = CString::new(name)?;
1256        check_status!(
1257          unsafe { sys::napi_set_named_property(self.env, this.object.raw(), name.as_ptr(), self.raw_value) },
1258          "Failed to assign {} to this",
1259          $slice_type::type_name()
1260        )?;
1261        Ok($slice_type {
1262          env: self.env,
1263          raw_value: self.raw_value,
1264          inner: self.inner,
1265          length: self.length,
1266          _marker: PhantomData,
1267        })
1268      }
1269
1270      #[allow(clippy::should_implement_trait)]
1271      /// # Safety
1272      ///
1273      /// This is literally undefined behavior, as the JS side may always modify the underlying buffer,
1274      /// without synchronization.
1275      pub unsafe fn as_mut(&mut self) -> &mut [$rust_type] {
1276        unsafe { core::slice::from_raw_parts_mut(self.inner.as_ptr(), self.length) }
1277      }
1278
1279      #[doc = "Convert a `"]
1280      #[doc = stringify!($slice_type)]
1281      #[doc = "` to a `"]
1282      #[doc = stringify!($name)]
1283      #[doc = "`."]
1284      #[doc = ""]
1285      #[doc = "This will perform a `napi_create_reference` internally."]
1286      pub fn into_typed_array(self, env: &Env) -> Result<$name> {
1287        unsafe { $name::from_napi_value(env.0, self.raw_value) }
1288      }
1289    }
1290
1291    impl<'env> JsValue<'env> for $slice_type<'env> {
1292      fn value(&self) -> Value {
1293        Value {
1294          env: self.env,
1295          value: self.raw_value,
1296          value_type: ValueType::Object,
1297        }
1298      }
1299    }
1300
1301    impl<'env> JsObjectValue<'env> for $slice_type<'env> { }
1302
1303    impl ToNapiValue for &$slice_type<'_> {
1304      unsafe fn to_napi_value(_: sys::napi_env, val: Self) -> Result<sys::napi_value> {
1305        Ok(val.raw_value)
1306      }
1307    }
1308
1309    impl ToNapiValue for &mut $slice_type<'_> {
1310      unsafe fn to_napi_value(_: sys::napi_env, val: Self) -> Result<sys::napi_value> {
1311        Ok(val.raw_value)
1312      }
1313    }
1314
1315    impl FromNapiValue for $slice_type<'_> {
1316      unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
1317        let mut typed_array_type = 0;
1318        let mut length = 0;
1319        let mut data = ptr::null_mut();
1320        let mut array_buffer = ptr::null_mut();
1321        let mut byte_offset = 0;
1322        check_status!(
1323          unsafe {
1324            sys::napi_get_typedarray_info(
1325              env,
1326              napi_val,
1327              &mut typed_array_type,
1328              &mut length,
1329              &mut data,
1330              &mut array_buffer,
1331              &mut byte_offset,
1332            )
1333          },
1334          "Get TypedArray info failed"
1335        )?;
1336        if typed_array_type != $typed_array_type as i32 {
1337          return Err(Error::new(
1338            Status::InvalidArg,
1339            format!("Expected $name, got {}", typed_array_type),
1340          ));
1341        }
1342        // From the docs of `napi_get_typedarray_info`:
1343        // > [out] data: The underlying data buffer of the node::Buffer. If length is 0, this may be
1344        // > NULL or any other pointer value.
1345        //
1346        // In order to guarantee that `slice::from_raw_parts` is sound, the pointer must be non-null, so
1347        // let's make sure it always is, even in the case of `napi_get_typedarray_info` returning a null
1348        // ptr.
1349        Ok(Self {
1350          inner: if length == 0 {
1351            ptr::NonNull::dangling()
1352          } else {
1353            ptr::NonNull::new_unchecked(data.cast())
1354          },
1355          length,
1356          raw_value: napi_val,
1357          env,
1358          _marker: PhantomData,
1359        })
1360      }
1361    }
1362
1363    impl TypeName for $slice_type<'_> {
1364      fn type_name() -> &'static str {
1365        concat!("TypedArray<", stringify!($rust_type), ">")
1366      }
1367
1368      fn value_type() -> crate::ValueType {
1369        crate::ValueType::Object
1370      }
1371    }
1372
1373    impl ValidateNapiValue for $slice_type<'_> {
1374      unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
1375        let mut is_typed_array = false;
1376        check_status!(
1377          unsafe { sys::napi_is_typedarray(env, napi_val, &mut is_typed_array) },
1378          "Failed to validate napi typed array"
1379        )?;
1380        if !is_typed_array {
1381          return Err(Error::new(
1382            Status::InvalidArg,
1383            "Expected a TypedArray value".to_owned(),
1384          ));
1385        }
1386        Ok(ptr::null_mut())
1387      }
1388    }
1389
1390    impl AsRef<[$rust_type]> for $slice_type<'_> {
1391      fn as_ref(&self) -> &[$rust_type] {
1392        unsafe { core::slice::from_raw_parts(self.inner.as_ptr(), self.length) }
1393      }
1394    }
1395
1396    impl Deref for $slice_type<'_> {
1397      type Target = [$rust_type];
1398
1399      fn deref(&self) -> &Self::Target {
1400        self.as_ref()
1401      }
1402    }
1403
1404    impl FromNapiValue for &mut [$rust_type] {
1405      unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
1406        let mut typed_array_type = 0;
1407        let mut length = 0;
1408        let mut data = ptr::null_mut();
1409        let mut array_buffer = ptr::null_mut();
1410        let mut byte_offset = 0;
1411        check_status!(
1412          unsafe {
1413            sys::napi_get_typedarray_info(
1414              env,
1415              napi_val,
1416              &mut typed_array_type,
1417              &mut length,
1418              &mut data,
1419              &mut array_buffer,
1420              &mut byte_offset,
1421            )
1422          },
1423          "Get TypedArray info failed"
1424        )?;
1425        if typed_array_type != $typed_array_type as i32 {
1426          return Err(Error::new(
1427            Status::InvalidArg,
1428            format!("Expected $name, got {}", typed_array_type),
1429          ));
1430        }
1431        Ok(if length == 0 {
1432          &mut []
1433        } else {
1434          unsafe { core::slice::from_raw_parts_mut(data as *mut $rust_type, length) }
1435        })
1436      }
1437    }
1438
1439    impl FromNapiValue for &[$rust_type] {
1440      unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
1441        let mut typed_array_type = 0;
1442        let mut length = 0;
1443        let mut data = ptr::null_mut();
1444        let mut array_buffer = ptr::null_mut();
1445        let mut byte_offset = 0;
1446        check_status!(
1447          unsafe {
1448            sys::napi_get_typedarray_info(
1449              env,
1450              napi_val,
1451              &mut typed_array_type,
1452              &mut length,
1453              &mut data,
1454              &mut array_buffer,
1455              &mut byte_offset,
1456            )
1457          },
1458          "Get TypedArray info failed"
1459        )?;
1460        if typed_array_type != $typed_array_type as i32 {
1461          return Err(Error::new(
1462            Status::InvalidArg,
1463            format!("Expected $name, got {}", typed_array_type),
1464          ));
1465        }
1466        Ok(if length == 0 {
1467          &[]
1468        } else {
1469          unsafe { core::slice::from_raw_parts_mut(data as *mut $rust_type, length) }
1470        })
1471      }
1472    }
1473
1474    impl TypeName for &mut [$rust_type] {
1475      fn type_name() -> &'static str {
1476        concat!("TypedArray<", stringify!($rust_type), ">")
1477      }
1478
1479      fn value_type() -> crate::ValueType {
1480        crate::ValueType::Object
1481      }
1482    }
1483
1484    impl TypeName for &[$rust_type] {
1485      fn type_name() -> &'static str {
1486        concat!("TypedArray<", stringify!($rust_type), ">")
1487      }
1488
1489      fn value_type() -> crate::ValueType {
1490        crate::ValueType::Object
1491      }
1492    }
1493
1494    impl ValidateNapiValue for &[$rust_type] {
1495      unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
1496        let mut is_typed_array = false;
1497        check_status!(
1498          unsafe { sys::napi_is_typedarray(env, napi_val, &mut is_typed_array) },
1499          "Failed to validate napi typed array"
1500        )?;
1501        if !is_typed_array {
1502          return Err(Error::new(
1503            Status::InvalidArg,
1504            "Expected a TypedArray value".to_owned(),
1505          ));
1506        }
1507        Ok(ptr::null_mut())
1508      }
1509    }
1510
1511    impl ValidateNapiValue for &mut [$rust_type] {
1512      unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
1513        let mut is_typed_array = false;
1514        check_status!(
1515          unsafe { sys::napi_is_typedarray(env, napi_val, &mut is_typed_array) },
1516          "Failed to validate napi typed array"
1517        )?;
1518        if !is_typed_array {
1519          return Err(Error::new(
1520            Status::InvalidArg,
1521            "Expected a TypedArray value".to_owned(),
1522          ));
1523        }
1524        Ok(ptr::null_mut())
1525      }
1526    }
1527  };
1528}
1529
1530unsafe extern "C" fn finalizer<Data, T: Finalizer<RustType = Data> + AsRef<[Data]>>(
1531  _env: sys::napi_env,
1532  _finalize_data: *mut c_void,
1533  finalize_hint: *mut c_void,
1534) {
1535  let data = unsafe { *Box::from_raw(finalize_hint as *mut T) };
1536  drop(data);
1537}
1538
1539unsafe extern "C" fn finalize_slice<Data>(
1540  _env: sys::napi_env,
1541  finalize_data: *mut c_void,
1542  finalize_hint: *mut c_void,
1543) {
1544  let (length, capacity): (usize, usize) =
1545    *unsafe { Box::from_raw(finalize_hint as *mut (usize, usize)) };
1546  if finalize_data.is_null() {
1547    return;
1548  }
1549  unsafe { Vec::from_raw_parts(finalize_data as *mut Data, length, capacity) };
1550}
1551
1552impl_typed_array!(Int8Array, i8, TypedArrayType::Int8);
1553impl_from_slice!(Int8Array, Int8ArraySlice, i8, TypedArrayType::Int8);
1554impl_typed_array!(Uint8Array, u8, TypedArrayType::Uint8);
1555impl_from_slice!(Uint8Array, Uint8ArraySlice, u8, TypedArrayType::Uint8);
1556impl_typed_array!(Uint8ClampedArray, u8, TypedArrayType::Uint8Clamped);
1557impl_typed_array!(Int16Array, i16, TypedArrayType::Int16);
1558impl_from_slice!(Int16Array, Int16ArraySlice, i16, TypedArrayType::Int16);
1559impl_typed_array!(Uint16Array, u16, TypedArrayType::Uint16);
1560impl_from_slice!(Uint16Array, Uint16ArraySlice, u16, TypedArrayType::Uint16);
1561impl_typed_array!(Int32Array, i32, TypedArrayType::Int32);
1562impl_from_slice!(Int32Array, Int32ArraySlice, i32, TypedArrayType::Int32);
1563impl_typed_array!(Uint32Array, u32, TypedArrayType::Uint32);
1564impl_from_slice!(Uint32Array, Uint32ArraySlice, u32, TypedArrayType::Uint32);
1565impl_typed_array!(Float32Array, f32, TypedArrayType::Float32);
1566impl_from_slice!(
1567  Float32Array,
1568  Float32ArraySlice,
1569  f32,
1570  TypedArrayType::Float32
1571);
1572impl_typed_array!(Float64Array, f64, TypedArrayType::Float64);
1573impl_from_slice!(
1574  Float64Array,
1575  Float64ArraySlice,
1576  f64,
1577  TypedArrayType::Float64
1578);
1579#[cfg(feature = "napi6")]
1580impl_typed_array!(BigInt64Array, i64, TypedArrayType::BigInt64);
1581#[cfg(feature = "napi6")]
1582impl_from_slice!(
1583  BigInt64Array,
1584  BigInt64ArraySlice,
1585  i64,
1586  TypedArrayType::BigInt64
1587);
1588#[cfg(feature = "napi6")]
1589impl_typed_array!(BigUint64Array, u64, TypedArrayType::BigUint64);
1590#[cfg(feature = "napi6")]
1591impl_from_slice!(
1592  BigUint64Array,
1593  BigUint64ArraySlice,
1594  u64,
1595  TypedArrayType::BigUint64
1596);
1597
1598impl Uint8Array {
1599  /// Create a new JavaScript `Uint8Array` from a Rust `String` without copying the underlying data.
1600  pub fn from_string(mut s: String) -> Self {
1601    let len = s.len();
1602    let cap = s.capacity();
1603    let ret = Self {
1604      data: s.as_mut_ptr(),
1605      length: len,
1606      capacity: cap,
1607      finalizer_notify: Box::into_raw(Box::new(move |data, _| {
1608        drop(unsafe { String::from_raw_parts(data, len, cap) });
1609      })),
1610      byte_offset: 0,
1611      raw: None,
1612      #[cfg(all(feature = "napi4", not(feature = "noop")))]
1613      custom_gc_handle: None,
1614    };
1615    mem::forget(s);
1616    ret
1617  }
1618}
1619
1620#[derive(Clone, Copy)]
1621/// Zero copy Uint8ClampedArray slice shared between Rust and Node.js.
1622/// It can only be used in non-async context and the lifetime is bound to the fn closure.
1623/// If you want to use Node.js `Uint8ClampedArray` in async context or want to extend the lifetime, use `Uint8ClampedArray` instead.
1624pub struct Uint8ClampedSlice<'scope> {
1625  pub(crate) inner: NonNull<u8>,
1626  pub(crate) length: usize,
1627  raw_value: sys::napi_value,
1628  env: sys::napi_env,
1629  _marker: PhantomData<&'scope ()>,
1630}
1631
1632impl FromNapiValue for Uint8ClampedSlice<'_> {
1633  unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
1634    let mut typed_array_type = 0;
1635    let mut length = 0;
1636    let mut data = ptr::null_mut();
1637    let mut array_buffer = ptr::null_mut();
1638    let mut byte_offset = 0;
1639    check_status!(
1640      unsafe {
1641        sys::napi_get_typedarray_info(
1642          env,
1643          napi_val,
1644          &mut typed_array_type,
1645          &mut length,
1646          &mut data,
1647          &mut array_buffer,
1648          &mut byte_offset,
1649        )
1650      },
1651      "Get TypedArray info failed"
1652    )?;
1653    if typed_array_type != TypedArrayType::Uint8Clamped as i32 {
1654      return Err(Error::new(
1655        Status::InvalidArg,
1656        format!("Expected $name, got {typed_array_type}"),
1657      ));
1658    }
1659    Ok(Self {
1660      inner: if length == 0 {
1661        NonNull::dangling()
1662      } else {
1663        unsafe { NonNull::new_unchecked(data.cast()) }
1664      },
1665      length,
1666      raw_value: napi_val,
1667      env,
1668      _marker: PhantomData,
1669    })
1670  }
1671}
1672
1673impl<'env> JsValue<'env> for Uint8ClampedSlice<'env> {
1674  fn value(&self) -> Value {
1675    Value {
1676      env: self.env,
1677      value: self.raw_value,
1678      value_type: ValueType::Object,
1679    }
1680  }
1681}
1682
1683impl<'env> JsObjectValue<'env> for Uint8ClampedSlice<'env> {}
1684
1685impl TypeName for Uint8ClampedSlice<'_> {
1686  fn type_name() -> &'static str {
1687    "Uint8ClampedArray"
1688  }
1689
1690  fn value_type() -> ValueType {
1691    ValueType::Object
1692  }
1693}
1694
1695impl ValidateNapiValue for Uint8ClampedSlice<'_> {
1696  unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
1697    let mut is_typedarray = false;
1698    check_status!(
1699      unsafe { sys::napi_is_typedarray(env, napi_val, &mut is_typedarray) },
1700      "Failed to validate typed buffer"
1701    )?;
1702    if !is_typedarray {
1703      return Err(Error::new(
1704        Status::InvalidArg,
1705        "Expected a TypedArray value".to_owned(),
1706      ));
1707    }
1708    Ok(ptr::null_mut())
1709  }
1710}
1711
1712impl AsRef<[u8]> for Uint8ClampedSlice<'_> {
1713  fn as_ref(&self) -> &[u8] {
1714    unsafe { core::slice::from_raw_parts(self.inner.as_ptr(), self.length) }
1715  }
1716}
1717
1718impl Deref for Uint8ClampedSlice<'_> {
1719  type Target = [u8];
1720
1721  fn deref(&self) -> &Self::Target {
1722    unsafe { core::slice::from_raw_parts(self.inner.as_ptr(), self.length) }
1723  }
1724}
1725
1726impl<'env> Uint8ClampedSlice<'env> {
1727  /// Create a new `Uint8ClampedSlice` from Vec<u8>
1728  pub fn from_data<D: Into<Vec<u8>>>(env: &Env, data: D) -> Result<Self> {
1729    let mut buf = ptr::null_mut();
1730    let mut data: Vec<u8> = data.into();
1731    let mut inner_ptr = data.as_mut_ptr();
1732    #[cfg(all(debug_assertions, not(windows), not(target_family = "wasm")))]
1733    {
1734      let is_existed = super::BUFFER_DATA.with(|buffer_data| {
1735        let buffer = buffer_data.lock().expect("Unlock buffer data failed");
1736        buffer.contains(&inner_ptr)
1737      });
1738      if is_existed {
1739        panic!("Share the same data between different buffers is not allowed, see: https://github.com/nodejs/node/issues/32463#issuecomment-631974747");
1740      }
1741    }
1742    let len = data.len();
1743    let cap = data.capacity();
1744    let finalize_hint = Box::into_raw(Box::new((len, cap)));
1745    let mut status = unsafe {
1746      sys::napi_create_external_arraybuffer(
1747        env.0,
1748        inner_ptr.cast(),
1749        data.len(),
1750        Some(finalize_slice::<u8>),
1751        finalize_hint.cast(),
1752        &mut buf,
1753      )
1754    };
1755    if status == napi_sys::Status::napi_no_external_buffers_allowed {
1756      unsafe {
1757        let _ = Box::from_raw(finalize_hint);
1758      }
1759      let mut underlying_data = ptr::null_mut();
1760      status = unsafe { sys::napi_create_arraybuffer(env.0, len, &mut underlying_data, &mut buf) };
1761      check_status!(status, "Failed to create arraybuffer")?;
1762      if len > 0 {
1763        let underlying_slice: &mut [u8] =
1764          unsafe { std::slice::from_raw_parts_mut(underlying_data.cast(), len) };
1765        underlying_slice.copy_from_slice(data.as_slice());
1766      }
1767      inner_ptr = underlying_data.cast();
1768    } else {
1769      check_status!(status, "Failed to create arraybuffer")?;
1770      mem::forget(data);
1771    }
1772
1773    let mut napi_val = ptr::null_mut();
1774    check_status!(
1775      unsafe {
1776        sys::napi_create_typedarray(
1777          env.0,
1778          TypedArrayType::Uint8Clamped as i32,
1779          len,
1780          buf,
1781          0,
1782          &mut napi_val,
1783        )
1784      },
1785      "Create TypedArray failed"
1786    )?;
1787
1788    Ok(Self {
1789      inner: if len == 0 {
1790        NonNull::dangling()
1791      } else {
1792        unsafe { NonNull::new_unchecked(inner_ptr.cast()) }
1793      },
1794      length: len,
1795      raw_value: napi_val,
1796      env: env.0,
1797      _marker: PhantomData,
1798    })
1799  }
1800
1801  /// Mostly the same with `from_data`
1802  ///
1803  /// Provided `finalize_callback` will be called when `Uint8ClampedSlice` got dropped.
1804  /// You can pass in `noop_finalize` if you have nothing to do in finalize phase.
1805  ///
1806  /// ## Safety
1807  ///
1808  /// The caller must ensure that:
1809  /// - The data pointer is valid for the lifetime of the buffer and points to a memory region of at least `len` bytes
1810  /// - The finalize callback properly cleans up the data
1811  ///
1812  /// ### Notes
1813  ///
1814  /// JavaScript may mutate the data passed in to this buffer when writing the buffer.
1815  /// However, some JavaScript runtimes do not support external buffers (notably electron!)
1816  /// in which case modifications may be lost.
1817  ///
1818  /// If you need to support these runtimes, you should create a buffer by other means and then
1819  /// later copy the data back out.
1820  pub unsafe fn from_external<T: 'env, F: FnOnce(Env, T)>(
1821    env: &Env,
1822    data: *mut u8,
1823    len: usize,
1824    finalize_hint: T,
1825    finalize_callback: F,
1826  ) -> Result<Self> {
1827    if data.is_null() || std::ptr::eq(data, crate::EMPTY_VEC.as_ptr()) {
1828      return Err(Error::new(
1829        Status::InvalidArg,
1830        "Borrowed data should not be null".to_owned(),
1831      ));
1832    }
1833    #[cfg(all(debug_assertions, not(windows), not(target_family = "wasm")))]
1834    {
1835      let is_existed = super::BUFFER_DATA.with(|buffer_data| {
1836        let buffer = buffer_data.lock().expect("Unlock buffer data failed");
1837        buffer.contains(&data)
1838      });
1839      if is_existed {
1840        panic!("Share the same data between different buffers is not allowed, see: https://github.com/nodejs/node/issues/32463#issuecomment-631974747");
1841      }
1842    }
1843    let hint_ptr = Box::into_raw(Box::new((finalize_hint, finalize_callback)));
1844    let mut arraybuffer_value = ptr::null_mut();
1845    let mut status = unsafe {
1846      sys::napi_create_external_arraybuffer(
1847        env.0,
1848        data.cast(),
1849        len,
1850        Some(crate::env::raw_finalize_with_custom_callback::<T, F>),
1851        hint_ptr.cast(),
1852        &mut arraybuffer_value,
1853      )
1854    };
1855    // `finalize` below reclaims `data`; on the copy fallback `inner` must
1856    // point at the engine-owned copy instead.
1857    let mut inner_ptr: *mut u8 = data;
1858    if status == sys::Status::napi_no_external_buffers_allowed {
1859      let (hint, finalize) = *Box::from_raw(hint_ptr);
1860      let mut underlying_data = ptr::null_mut();
1861      status = unsafe {
1862        sys::napi_create_arraybuffer(env.0, len, &mut underlying_data, &mut arraybuffer_value)
1863      };
1864      // Copy data before calling finalize, since finalize may free the source data
1865      if status == sys::Status::napi_ok && len > 0 {
1866        let underlying_slice: &mut [u8] =
1867          unsafe { std::slice::from_raw_parts_mut(underlying_data.cast(), len) };
1868        underlying_slice.copy_from_slice(unsafe { std::slice::from_raw_parts(data, len) });
1869      }
1870      // Always call finalize to clean up caller's resources, even on error
1871      finalize(*env, hint);
1872      check_status!(status, "Failed to create arraybuffer from data")?;
1873      inner_ptr = underlying_data.cast();
1874    } else {
1875      check_status!(status, "Failed to create arraybuffer from data")?;
1876    }
1877
1878    let mut napi_val = ptr::null_mut();
1879    check_status!(
1880      unsafe {
1881        sys::napi_create_typedarray(
1882          env.0,
1883          TypedArrayType::Uint8Clamped as i32,
1884          len,
1885          arraybuffer_value,
1886          0,
1887          &mut napi_val,
1888        )
1889      },
1890      "Create TypedArray failed"
1891    )?;
1892
1893    Ok(Self {
1894      inner: if len == 0 {
1895        NonNull::dangling()
1896      } else {
1897        unsafe { NonNull::new_unchecked(inner_ptr) }
1898      },
1899      length: len,
1900      raw_value: napi_val,
1901      env: env.0,
1902      _marker: PhantomData,
1903    })
1904  }
1905
1906  /// Copy data from a `&[u8]` and create a `Uint8ClampedSlice` from it.
1907  pub fn copy_from<D: AsRef<[u8]>>(env: &Env, data: D) -> Result<Self> {
1908    let data = data.as_ref();
1909    let len = data.len();
1910    let mut arraybuffer_value = ptr::null_mut();
1911    let mut underlying_data = ptr::null_mut();
1912
1913    check_status!(
1914      unsafe {
1915        sys::napi_create_arraybuffer(env.0, len, &mut underlying_data, &mut arraybuffer_value)
1916      },
1917      "Failed to create ArrayBuffer"
1918    )?;
1919
1920    let mut napi_val = ptr::null_mut();
1921    check_status!(
1922      unsafe {
1923        sys::napi_create_typedarray(
1924          env.0,
1925          TypedArrayType::Uint8Clamped as i32,
1926          len,
1927          arraybuffer_value,
1928          0,
1929          &mut napi_val,
1930        )
1931      },
1932      "Create TypedArray failed"
1933    )?;
1934
1935    Ok(Self {
1936      inner: if len == 0 {
1937        NonNull::dangling()
1938      } else {
1939        unsafe { NonNull::new_unchecked(underlying_data.cast()) }
1940      },
1941      length: len,
1942      raw_value: napi_val,
1943      env: env.0,
1944      _marker: PhantomData,
1945    })
1946  }
1947
1948  /// Create from `ArrayBuffer`
1949  pub fn from_arraybuffer(
1950    arraybuffer: &ArrayBuffer<'env>,
1951    byte_offset: usize,
1952    length: usize,
1953  ) -> Result<Self> {
1954    let env = arraybuffer.value.env;
1955    let mut typed_array = ptr::null_mut();
1956    check_status!(
1957      unsafe {
1958        sys::napi_create_typedarray(
1959          env,
1960          TypedArrayType::Uint8Clamped as i32,
1961          length,
1962          arraybuffer.value().value,
1963          byte_offset,
1964          &mut typed_array,
1965        )
1966      },
1967      "Failed to create TypedArray from ArrayBuffer"
1968    )?;
1969
1970    unsafe { FromNapiValue::from_napi_value(env, typed_array) }
1971  }
1972
1973  /// extends the lifetime of the `TypedArray` to the lifetime of the `This`
1974  pub fn assign_to_this<'a, U>(&self, this: This<'a, U>, name: &str) -> Result<Self>
1975  where
1976    U: FromNapiValue + JsObjectValue<'a>,
1977  {
1978    let name = CString::new(name)?;
1979    check_status!(
1980      unsafe {
1981        sys::napi_set_named_property(self.env, this.object.raw(), name.as_ptr(), self.raw_value)
1982      },
1983      "Failed to assign {} to this",
1984      Self::type_name()
1985    )?;
1986    Ok(Self {
1987      env: self.env,
1988      raw_value: self.raw_value,
1989      inner: self.inner,
1990      length: self.length,
1991      _marker: PhantomData,
1992    })
1993  }
1994
1995  #[allow(clippy::should_implement_trait)]
1996  /// # Safety
1997  ///
1998  /// This is literally undefined behavior, as the JS side may always modify the underlying buffer,
1999  /// without synchronization.
2000  pub unsafe fn as_mut(&mut self) -> &mut [u8] {
2001    core::slice::from_raw_parts_mut(self.inner.as_ptr(), self.length)
2002  }
2003
2004  /// Convert a `Uint8ClampedSlice` to a `Uint8ClampedArray`.
2005  pub fn into_typed_array(self, env: &Env) -> Result<Self> {
2006    unsafe { Self::from_napi_value(env.0, self.raw_value) }
2007  }
2008}
2009
2010impl<T: Into<Vec<u8>>> From<T> for Uint8Array {
2011  fn from(data: T) -> Self {
2012    Uint8Array::new(data.into())
2013  }
2014}
2015
2016impl<T: Into<Vec<u8>>> From<T> for Uint8ClampedArray {
2017  fn from(data: T) -> Self {
2018    Uint8ClampedArray::new(data.into())
2019  }
2020}
2021
2022impl<T: Into<Vec<u16>>> From<T> for Uint16Array {
2023  fn from(data: T) -> Self {
2024    Uint16Array::new(data.into())
2025  }
2026}
2027
2028impl<T: Into<Vec<u32>>> From<T> for Uint32Array {
2029  fn from(data: T) -> Self {
2030    Uint32Array::new(data.into())
2031  }
2032}
2033
2034impl<T: Into<Vec<i8>>> From<T> for Int8Array {
2035  fn from(data: T) -> Self {
2036    Int8Array::new(data.into())
2037  }
2038}
2039
2040impl<T: Into<Vec<i16>>> From<T> for Int16Array {
2041  fn from(data: T) -> Self {
2042    Int16Array::new(data.into())
2043  }
2044}
2045
2046impl<T: Into<Vec<i32>>> From<T> for Int32Array {
2047  fn from(data: T) -> Self {
2048    Int32Array::new(data.into())
2049  }
2050}
2051
2052impl<T: Into<Vec<f32>>> From<T> for Float32Array {
2053  fn from(data: T) -> Self {
2054    Float32Array::new(data.into())
2055  }
2056}
2057
2058impl<T: Into<Vec<f64>>> From<T> for Float64Array {
2059  fn from(data: T) -> Self {
2060    Float64Array::new(data.into())
2061  }
2062}
2063
2064#[cfg(feature = "napi6")]
2065impl<T: Into<Vec<i64>>> From<T> for BigInt64Array {
2066  fn from(data: T) -> Self {
2067    BigInt64Array::new(data.into())
2068  }
2069}
2070#[cfg(feature = "napi6")]
2071impl<T: Into<Vec<u64>>> From<T> for BigUint64Array {
2072  fn from(data: T) -> Self {
2073    BigUint64Array::new(data.into())
2074  }
2075}