ferrijs_std/buffer/
array_buffer_view.rs1#![allow(clippy::uninlined_format_args)]
4
5use std::ptr::NonNull;
6
7use rquickjs::{ArrayBuffer, Ctx, Error, FromJs, IntoJs, Object, Result, TypedArray, Value};
8
9use crate::buffer::Buffer;
10
11pub struct ArrayBufferView<'js> {
12 value: Value<'js>,
13 buffer: Option<RawArrayBuffer>,
14}
15
16struct RawArrayBuffer {
17 len: usize,
18 ptr: NonNull<u8>,
19}
20
21impl RawArrayBuffer {
22 pub fn new(len: usize, ptr: NonNull<u8>) -> Self {
23 Self { len, ptr }
24 }
25}
26
27impl<'js> IntoJs<'js> for ArrayBufferView<'js> {
28 fn into_js(self, _ctx: &Ctx<'js>) -> Result<Value<'js>> {
29 Ok(self.value)
30 }
31}
32
33impl<'js> FromJs<'js> for ArrayBufferView<'js> {
34 fn from_js(_ctx: &Ctx<'js>, value: Value<'js>) -> Result<Self> {
35 let ty_name = value.type_name();
36 let obj = Object::from_value(value.clone())
37 .map_err(|_| Error::new_from_js(ty_name, "ArrayBufferView"))?;
38
39 if let Some(array_buffer) = ArrayBuffer::from_object(obj.clone()) {
40 let buffer = array_buffer
41 .as_raw()
42 .map(|raw| RawArrayBuffer::new(raw.len(), raw.cast::<u8>()));
43 return Ok(ArrayBufferView { value, buffer });
44 }
45
46 if let Ok(typed_array) = TypedArray::<i8>::from_object(obj.clone()) {
47 let buffer = typed_array
48 .as_raw()
49 .map(|raw| RawArrayBuffer::new(raw.len(), raw.cast::<u8>()));
50 return Ok(ArrayBufferView { value, buffer });
51 }
52
53 if let Ok(typed_array) = TypedArray::<u8>::from_object(obj.clone()) {
54 let buffer = typed_array
55 .as_raw()
56 .map(|raw| RawArrayBuffer::new(raw.len(), raw.cast::<u8>()));
57 return Ok(ArrayBufferView { value, buffer });
58 }
59
60 if let Ok(typed_array) = TypedArray::<i16>::from_object(obj.clone()) {
61 let buffer = typed_array
62 .as_raw()
63 .map(|raw| RawArrayBuffer::new(raw.len(), raw.cast::<u8>()));
64 return Ok(ArrayBufferView { value, buffer });
65 }
66
67 if let Ok(typed_array) = TypedArray::<u16>::from_object(obj.clone()) {
68 let buffer = typed_array
69 .as_raw()
70 .map(|raw| RawArrayBuffer::new(raw.len(), raw.cast::<u8>()));
71 return Ok(ArrayBufferView { value, buffer });
72 }
73
74 if let Ok(typed_array) = TypedArray::<i32>::from_object(obj.clone()) {
75 let buffer = typed_array
76 .as_raw()
77 .map(|raw| RawArrayBuffer::new(raw.len(), raw.cast::<u8>()));
78 return Ok(ArrayBufferView { value, buffer });
79 }
80
81 if let Ok(typed_array) = TypedArray::<u32>::from_object(obj.clone()) {
82 let buffer = typed_array
83 .as_raw()
84 .map(|raw| RawArrayBuffer::new(raw.len(), raw.cast::<u8>()));
85 return Ok(ArrayBufferView { value, buffer });
86 }
87
88 if let Ok(typed_array) = TypedArray::<f32>::from_object(obj.clone()) {
89 let buffer = typed_array
90 .as_raw()
91 .map(|raw| RawArrayBuffer::new(raw.len(), raw.cast::<u8>()));
92 return Ok(ArrayBufferView { value, buffer });
93 }
94
95 if let Ok(typed_array) = TypedArray::<f64>::from_object(obj.clone()) {
96 let buffer = typed_array
97 .as_raw()
98 .map(|raw| RawArrayBuffer::new(raw.len(), raw.cast::<u8>()));
99 return Ok(ArrayBufferView { value, buffer });
100 }
101
102 if let Ok(typed_array) = TypedArray::<i64>::from_object(obj.clone()) {
103 let buffer = typed_array
104 .as_raw()
105 .map(|raw| RawArrayBuffer::new(raw.len(), raw.cast::<u8>()));
106 return Ok(ArrayBufferView { value, buffer });
107 }
108
109 if let Ok(typed_array) = TypedArray::<u64>::from_object(obj.clone()) {
110 let buffer = typed_array
111 .as_raw()
112 .map(|raw| RawArrayBuffer::new(raw.len(), raw.cast::<u8>()));
113 return Ok(ArrayBufferView { value, buffer });
114 }
115
116 if let Ok(array_buffer) = obj.get::<_, ArrayBuffer>("buffer") {
117 let buffer = array_buffer
118 .as_raw()
119 .map(|raw| RawArrayBuffer::new(raw.len(), raw.cast::<u8>()));
120 return Ok(ArrayBufferView { value, buffer });
121 }
122
123 Err(Error::new_from_js(ty_name, "ArrayBufferView"))
124 }
125}
126
127impl<'js> ArrayBufferView<'js> {
128 pub fn from_buffer(ctx: &Ctx<'js>, buffer: Buffer) -> Result<Self> {
129 let value = buffer.into_js(ctx)?;
130 Self::from_js(ctx, value)
131 }
132
133 pub fn len(&self) -> usize {
134 self.buffer.as_ref().map(|b| b.len).unwrap_or(0)
135 }
136
137 #[allow(dead_code)]
138 pub fn is_empty(&self) -> bool {
139 self.len() == 0
140 }
141
142 pub fn as_bytes(&self) -> Option<&[u8]> {
143 self.buffer
144 .as_ref()
145 .map(|b| unsafe { std::slice::from_raw_parts(b.ptr.as_ptr(), b.len) })
146 }
147
148 pub fn as_bytes_mut(&mut self) -> Option<&mut [u8]> {
154 self.buffer
155 .as_ref()
156 .map(|b| unsafe { std::slice::from_raw_parts_mut(b.ptr.as_ptr(), b.len) })
157 }
158}