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