ion/object/typedarray/
mod.rs1use std::mem::transmute;
8use std::ops::Deref;
9
10pub use buffer::*;
11use mozjs::jsapi::{
12 Handle, JS_NewDataView, JS_NewFloat32ArrayWithBuffer, JS_NewFloat64ArrayWithBuffer, JS_NewInt8ArrayWithBuffer,
13 JS_NewInt16ArrayWithBuffer, JS_NewInt32ArrayWithBuffer, JS_NewUint8ArrayWithBuffer,
14 JS_NewUint8ClampedArrayWithBuffer, JS_NewUint16ArrayWithBuffer, JS_NewUint32ArrayWithBuffer, JSContext, JSObject,
15 Type,
16};
17use mozjs::typedarray as jsta;
18use mozjs::typedarray::{ArrayBufferU8, ClampedU8, Float32, Float64, Int8, Int16, Int32, Uint8, Uint16, Uint32};
19pub use view::*;
20
21use crate::conversions::{IntoValue, ToValue as _};
22use crate::{Context, Value};
23
24mod buffer;
25mod view;
26
27pub struct ArrayBufferWrapper {
28 buf: Box<[<ArrayBufferU8 as jsta::TypedArrayElement>::Element]>,
29}
30
31impl ArrayBufferWrapper {
32 pub fn into_array_buffer(self, cx: &Context) -> Option<ArrayBuffer<'_>> {
33 ArrayBuffer::from_boxed_slice(cx, self.buf)
34 }
35}
36
37impl<B: Into<Box<[<ArrayBufferU8 as jsta::TypedArrayElement>::Element]>>> From<B> for ArrayBufferWrapper {
38 fn from(buffer: B) -> ArrayBufferWrapper {
39 ArrayBufferWrapper { buf: buffer.into() }
40 }
41}
42
43impl Deref for ArrayBufferWrapper {
44 type Target = Box<[<ArrayBufferU8 as jsta::TypedArrayElement>::Element]>;
45
46 fn deref(&self) -> &Self::Target {
47 &self.buf
48 }
49}
50
51impl<'cx> IntoValue<'cx> for ArrayBufferWrapper {
52 fn into_value(self: Box<Self>, cx: &'cx Context, value: &mut Value) {
53 if let Some(buffer) = self.into_array_buffer(cx) {
54 buffer.to_value(cx, value);
55 }
56 }
57}
58
59macro_rules! impl_typedarray_wrapper {
60 ($(($typedarray:ident, $element:ty)$(,)?)*) => {
61 $(
62 pub struct $typedarray {
63 buf: Box<[<$element as jsta::TypedArrayElement>::Element]>,
64 }
65
66 impl $typedarray {
67 pub fn into_typed_array(self, cx: &Context) -> Option<TypedArray<'_, $element>> {
68 TypedArray::from_boxed_slice(cx, self.buf)
69 }
70 }
71
72 impl<B: Into<Box<[<$element as jsta::TypedArrayElement>::Element]>>> From<B> for $typedarray {
73 fn from(buffer: B) -> $typedarray {
74 $typedarray { buf: buffer.into() }
75 }
76 }
77
78 impl Deref for $typedarray {
79 type Target = Box<[<$element as jsta::TypedArrayElement>::Element]>;
80
81 fn deref(&self) -> &Self::Target {
82 &self.buf
83 }
84 }
85
86 impl<'cx> IntoValue<'cx> for $typedarray {
87 fn into_value(self: Box<Self>, cx: &'cx Context, value: &mut Value) {
88 if let Some(array) = self.into_typed_array(cx) {
89 array.to_value(cx, value);
90 }
91 }
92 }
93 )*
94 };
95}
96
97impl_typedarray_wrapper!(
98 (Uint8ArrayWrapper, Uint8),
99 (Uint16ArrayWrapper, Uint16),
100 (Uint32ArrayWrapper, Uint32),
101 (Int8ArrayWrapper, Int8),
102 (Int16ArrayWrapper, Int16),
103 (Int32ArrayWrapper, Int32),
104 (Float32ArrayWrapper, Float32),
105 (Float64ArrayWrapper, Float64),
106 (ClampedUint8ArrayWrapper, ClampedU8),
107);
108
109pub type Constructor = unsafe extern "C" fn(*mut JSContext, Handle<*mut JSObject>, usize, i64) -> *mut JSObject;
110
111pub fn type_to_constructor(ty: Type) -> Constructor {
112 match ty {
113 Type::Int8 => JS_NewInt8ArrayWithBuffer,
114 Type::Uint8 => JS_NewUint8ArrayWithBuffer,
115 Type::Int16 => JS_NewInt16ArrayWithBuffer,
116 Type::Uint16 => JS_NewUint16ArrayWithBuffer,
117 Type::Int32 => JS_NewInt32ArrayWithBuffer,
118 Type::Uint32 => JS_NewUint32ArrayWithBuffer,
119 Type::Float32 => JS_NewFloat32ArrayWithBuffer,
120 Type::Float64 => JS_NewFloat64ArrayWithBuffer,
121 Type::Uint8Clamped => JS_NewUint8ClampedArrayWithBuffer,
122 Type::MaxTypedArrayViewType => unsafe {
123 transmute::<
124 unsafe extern "C" fn(*mut JSContext, Handle<*mut JSObject>, usize, usize) -> *mut JSObject,
125 unsafe extern "C" fn(*mut JSContext, Handle<*mut JSObject>, usize, i64) -> *mut JSObject,
126 >(JS_NewDataView)
127 },
128 _ => unreachable!(),
129 }
130}
131
132pub fn type_to_element_size(ty: Type) -> usize {
133 match ty {
134 Type::Int8 | Type::Uint8 | Type::Uint8Clamped | Type::MaxTypedArrayViewType => 1,
135 Type::Int16 | Type::Uint16 => 2,
136 Type::Int32 | Type::Uint32 | Type::Float32 => 4,
137 Type::BigInt64 | Type::BigUint64 | Type::Float64 => 8,
138 _ => unreachable!(),
139 }
140}