ul_next/javascript/
typed_array.rs1use std::ops::Deref;
2
3use super::{AsJSValue, JSContext, JSValue};
4
5#[repr(u32)]
7#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
8pub enum JSTypedArrayType {
9 Int8Array = ul_sys::JSTypedArrayType_kJSTypedArrayTypeInt8Array,
10 Int16Array = ul_sys::JSTypedArrayType_kJSTypedArrayTypeInt16Array,
11 Int32Array = ul_sys::JSTypedArrayType_kJSTypedArrayTypeInt32Array,
12 Uint8Array = ul_sys::JSTypedArrayType_kJSTypedArrayTypeUint8Array,
13 Uint8ClampedArray = ul_sys::JSTypedArrayType_kJSTypedArrayTypeUint8ClampedArray,
14 Uint16Array = ul_sys::JSTypedArrayType_kJSTypedArrayTypeUint16Array,
15 Uint32Array = ul_sys::JSTypedArrayType_kJSTypedArrayTypeUint32Array,
16 Float32Array = ul_sys::JSTypedArrayType_kJSTypedArrayTypeFloat32Array,
17 Float64Array = ul_sys::JSTypedArrayType_kJSTypedArrayTypeFloat64Array,
18 ArrayBuffer = ul_sys::JSTypedArrayType_kJSTypedArrayTypeArrayBuffer,
19 None = ul_sys::JSTypedArrayType_kJSTypedArrayTypeNone,
20 BigInt64Array = ul_sys::JSTypedArrayType_kJSTypedArrayTypeBigInt64Array,
21 BigUint64Array = ul_sys::JSTypedArrayType_kJSTypedArrayTypeBigUint64Array,
22}
23
24#[derive(Clone, Debug)]
26pub struct JSTypedArray<'a> {
27 pub(crate) value: JSValue<'a>,
28}
29
30impl<'a> JSTypedArray<'a> {
31 pub fn new(
36 ctx: &'a JSContext,
37 array_type: JSTypedArrayType,
38 length: usize,
39 ) -> Result<Self, JSValue<'a>> {
40 let mut exception = std::ptr::null();
41 let value = unsafe {
42 ctx.lib.ultralight().JSObjectMakeTypedArray(
43 ctx.internal,
44 array_type as _,
45 length,
46 &mut exception,
47 )
48 };
49
50 if !exception.is_null() {
51 Err(JSValue::from_raw(ctx, exception))
52 } else if value.is_null() {
53 return Err(JSValue::new_string(ctx, "Failed to create typed array"));
54 } else {
55 Ok(Self {
56 value: JSValue::from_raw(ctx, value),
57 })
58 }
59 }
60
61 pub fn new_copy_from_bytes(
67 ctx: &'a JSContext,
68 array_type: JSTypedArrayType,
69 bytes: &[u8],
70 ) -> Result<Self, JSValue<'a>> {
71 extern "C" fn deallocator(
72 bytes: *mut std::ffi::c_void,
73 deallocator_context: *mut std::ffi::c_void,
74 ) {
75 let slice_size = deallocator_context as usize;
76
77 drop(unsafe {
78 Box::from_raw(std::slice::from_raw_parts_mut(bytes as *mut u8, slice_size))
79 })
80 }
81
82 let mut exception = std::ptr::null();
83 let boxed_bytes = Vec::from(bytes).into_boxed_slice();
84
85 let date_size = boxed_bytes.len();
86 let data = Box::into_raw(boxed_bytes);
87
88 let value = unsafe {
89 ctx.lib.ultralight().JSObjectMakeTypedArrayWithBytesNoCopy(
90 ctx.internal,
91 array_type as _,
92 data as _,
93 bytes.len(),
94 Some(deallocator),
95 date_size as _,
96 &mut exception,
97 )
98 };
99
100 if !exception.is_null() {
101 Err(JSValue::from_raw(ctx, exception))
102 } else if value.is_null() {
103 return Err(JSValue::new_string(ctx, "Failed to create typed array"));
104 } else {
105 Ok(Self {
106 value: JSValue::from_raw(ctx, value),
107 })
108 }
109 }
110
111 pub fn len(&self) -> Result<usize, JSValue<'a>> {
115 let mut exception = std::ptr::null();
116
117 let result = unsafe {
118 self.value.ctx.lib.ultralight().JSObjectGetTypedArrayLength(
119 self.value.ctx.internal,
120 self.value.internal as _,
121 &mut exception,
122 )
123 };
124
125 if !exception.is_null() {
126 Err(JSValue::from_raw(self.value.ctx, exception))
127 } else {
128 Ok(result)
129 }
130 }
131
132 pub fn is_empty(&self) -> Result<bool, JSValue<'a>> {
136 self.len().map(|len| len == 0)
137 }
138
139 pub fn byte_length(&self) -> Result<usize, JSValue<'a>> {
143 let mut exception = std::ptr::null();
144
145 let result = unsafe {
146 self.value
147 .ctx
148 .lib
149 .ultralight()
150 .JSObjectGetTypedArrayByteLength(
151 self.value.ctx.internal,
152 self.value.internal as _,
153 &mut exception,
154 )
155 };
156
157 if !exception.is_null() {
158 Err(JSValue::from_raw(self.value.ctx, exception))
159 } else {
160 Ok(result)
161 }
162 }
163
164 pub fn byte_offset(&self) -> Result<usize, JSValue<'a>> {
168 let mut exception = std::ptr::null();
169
170 let result = unsafe {
171 self.value
172 .ctx
173 .lib
174 .ultralight()
175 .JSObjectGetTypedArrayByteOffset(
176 self.value.ctx.internal,
177 self.value.internal as _,
178 &mut exception,
179 )
180 };
181
182 if !exception.is_null() {
183 Err(JSValue::from_raw(self.value.ctx, exception))
184 } else {
185 Ok(result)
186 }
187 }
188
189 pub fn ty(&self) -> Result<JSTypedArrayType, JSValue<'a>> {
194 let mut exception = std::ptr::null();
195
196 let ty = unsafe {
197 self.value.ctx.lib.ultralight().JSValueGetTypedArrayType(
198 self.value.ctx.internal,
199 self.value.internal as _,
200 &mut exception,
201 )
202 };
203
204 if !exception.is_null() {
205 Err(JSValue::from_raw(self.value.ctx, exception))
206 } else {
207 match ty {
208 ul_sys::JSTypedArrayType_kJSTypedArrayTypeInt8Array => {
209 Ok(JSTypedArrayType::Int8Array)
210 }
211 ul_sys::JSTypedArrayType_kJSTypedArrayTypeInt16Array => {
212 Ok(JSTypedArrayType::Int16Array)
213 }
214 ul_sys::JSTypedArrayType_kJSTypedArrayTypeInt32Array => {
215 Ok(JSTypedArrayType::Int32Array)
216 }
217 ul_sys::JSTypedArrayType_kJSTypedArrayTypeUint8Array => {
218 Ok(JSTypedArrayType::Uint8Array)
219 }
220 ul_sys::JSTypedArrayType_kJSTypedArrayTypeUint8ClampedArray => {
221 Ok(JSTypedArrayType::Uint8ClampedArray)
222 }
223 ul_sys::JSTypedArrayType_kJSTypedArrayTypeUint16Array => {
224 Ok(JSTypedArrayType::Uint16Array)
225 }
226 ul_sys::JSTypedArrayType_kJSTypedArrayTypeUint32Array => {
227 Ok(JSTypedArrayType::Uint32Array)
228 }
229 ul_sys::JSTypedArrayType_kJSTypedArrayTypeFloat32Array => {
230 Ok(JSTypedArrayType::Float32Array)
231 }
232 ul_sys::JSTypedArrayType_kJSTypedArrayTypeFloat64Array => {
233 Ok(JSTypedArrayType::Float64Array)
234 }
235 ul_sys::JSTypedArrayType_kJSTypedArrayTypeArrayBuffer => {
236 Ok(JSTypedArrayType::ArrayBuffer)
237 }
238 ul_sys::JSTypedArrayType_kJSTypedArrayTypeNone => Ok(JSTypedArrayType::None),
239 ul_sys::JSTypedArrayType_kJSTypedArrayTypeBigInt64Array => {
240 Ok(JSTypedArrayType::BigInt64Array)
241 }
242 ul_sys::JSTypedArrayType_kJSTypedArrayTypeBigUint64Array => {
243 Ok(JSTypedArrayType::BigUint64Array)
244 }
245 _ => Err(JSValue::new_string(
246 self.value.ctx,
247 &format!("Unknown typed array type: {}", ty),
248 )),
249 }
250 }
251 }
252}
253
254impl<'a> AsRef<JSValue<'a>> for JSTypedArray<'a> {
255 fn as_ref(&self) -> &JSValue<'a> {
256 &self.value
257 }
258}
259
260impl<'a> Deref for JSTypedArray<'a> {
261 type Target = JSValue<'a>;
262
263 fn deref(&self) -> &Self::Target {
264 &self.value
265 }
266}
267
268impl<'a> AsJSValue<'a> for JSTypedArray<'a> {
269 fn into_value(self) -> JSValue<'a> {
270 self.value
271 }
272
273 fn as_value(&self) -> &JSValue<'a> {
274 &self.value
275 }
276}