1use crate::{
2 context::Cx,
3 handle::Handle,
4 result::{JsResult, NeonResult},
5 types::{
6 buffer::{Binary, TypedArray},
7 extract::{private, TryFromJs, TryIntoJs, TypeExpected},
8 JsArrayBuffer, JsBigInt64Array, JsBigUint64Array, JsBuffer, JsFloat32Array, JsFloat64Array,
9 JsInt16Array, JsInt32Array, JsInt8Array, JsTypedArray, JsUint16Array, JsUint32Array,
10 JsUint8Array, JsValue, Value,
11 },
12};
13
14pub struct ArrayBuffer<B>(pub B);
16
17impl<'cx, B> TryFromJs<'cx> for ArrayBuffer<B>
18where
19 for<'b> B: From<&'b [u8]>,
20{
21 type Error = TypeExpected<JsBuffer>;
22
23 fn try_from_js(
24 cx: &mut Cx<'cx>,
25 v: Handle<'cx, JsValue>,
26 ) -> NeonResult<Result<Self, Self::Error>> {
27 let v = match v.downcast::<JsArrayBuffer, _>(cx) {
28 Ok(v) => v,
29 Err(_) => return Ok(Err(Self::Error::new())),
30 };
31
32 Ok(Ok(ArrayBuffer(B::from(v.as_slice(cx)))))
33 }
34}
35
36impl<'cx, B> TryIntoJs<'cx> for ArrayBuffer<B>
37where
38 B: AsRef<[u8]>,
39{
40 type Value = JsArrayBuffer;
41
42 fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
43 JsArrayBuffer::from_slice(cx, self.0.as_ref())
44 }
45}
46
47impl<B> private::Sealed for ArrayBuffer<B> {}
48
49pub struct Buffer<B>(pub B);
51
52impl<'cx, B> TryFromJs<'cx> for Buffer<B>
53where
54 for<'b> B: From<&'b [u8]>,
55{
56 type Error = TypeExpected<JsBuffer>;
57
58 fn try_from_js(
59 cx: &mut Cx<'cx>,
60 v: Handle<'cx, JsValue>,
61 ) -> NeonResult<Result<Self, Self::Error>> {
62 let v = match v.downcast::<JsBuffer, _>(cx) {
63 Ok(v) => v,
64 Err(_) => return Ok(Err(Self::Error::new())),
65 };
66
67 Ok(Ok(Buffer(B::from(v.as_slice(cx)))))
68 }
69}
70
71impl<'cx, B> TryIntoJs<'cx> for Buffer<B>
72where
73 B: AsRef<[u8]>,
74{
75 type Value = JsBuffer;
76
77 fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
78 JsBuffer::from_slice(cx, self.0.as_ref())
79 }
80}
81
82impl<B> private::Sealed for Buffer<B> {}
83
84impl<'cx, T> TryIntoJs<'cx> for Vec<T>
85where
86 JsTypedArray<T>: Value,
87 T: Binary,
88{
89 type Value = JsTypedArray<T>;
90
91 fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
92 JsTypedArray::from_slice(cx, self.as_slice())
93 }
94}
95
96impl<'cx, T> TryFromJs<'cx> for Vec<T>
97where
98 JsTypedArray<T>: Value,
99 T: Binary,
100{
101 type Error = TypeExpected<JsTypedArray<T>>;
102
103 fn try_from_js(
104 cx: &mut Cx<'cx>,
105 v: Handle<'cx, JsValue>,
106 ) -> NeonResult<Result<Self, Self::Error>> {
107 let v = match v.downcast::<JsTypedArray<T>, _>(cx) {
108 Ok(v) => v,
109 Err(_) => return Ok(Err(Self::Error::new())),
110 };
111
112 Ok(Ok(v.as_slice(cx).to_vec()))
113 }
114}
115
116impl<T> private::Sealed for Vec<T>
117where
118 JsTypedArray<T>: Value,
119 T: Binary,
120{
121}
122
123impl<'cx, T, const N: usize> TryIntoJs<'cx> for [T; N]
124where
125 JsTypedArray<T>: Value,
126 T: Binary,
127{
128 type Value = JsTypedArray<T>;
129
130 fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
131 JsTypedArray::from_slice(cx, self.as_slice())
132 }
133}
134
135impl<T, const N: usize> private::Sealed for [T; N]
136where
137 JsTypedArray<T>: Value,
138 T: Binary,
139{
140}
141
142impl<'cx, T> TryIntoJs<'cx> for &[T]
143where
144 JsTypedArray<T>: Value,
145 T: Binary,
146{
147 type Value = JsTypedArray<T>;
148
149 fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
150 JsTypedArray::from_slice(cx, self)
151 }
152}
153
154impl<T> private::Sealed for &[T]
155where
156 JsTypedArray<T>: Value,
157 T: Binary,
158{
159}
160
161macro_rules! typed_array {
162 ($js:ident, $name:ident, $type:ty) => {
163 #[doc = concat!(
164 "Wrapper for converting between a Rust `[",
165 stringify!($type),
166 "]` array type and a [`",
167 stringify!($js),
168 "`]",
169 )]
170 pub struct $name<T>(pub T);
171
172 impl<'cx, T> TryIntoJs<'cx> for $name<T>
173 where
174 T: AsRef<[$type]>,
175 {
176 type Value = $js;
177
178 fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
179 $js::from_slice(cx, self.0.as_ref())
180 }
181 }
182
183 impl<'cx, T> TryFromJs<'cx> for $name<T>
184 where
185 for<'a> T: From<&'a [$type]>,
186 {
187 type Error = TypeExpected<$js>;
188
189 fn try_from_js(
190 cx: &mut Cx<'cx>,
191 v: Handle<'cx, JsValue>,
192 ) -> NeonResult<Result<Self, Self::Error>> {
193 let v = match v.downcast::<$js, _>(cx) {
194 Ok(v) => v,
195 Err(_) => return Ok(Err(TypeExpected::new())),
196 };
197
198 Ok(Ok(Self(T::from(v.as_slice(cx)))))
199 }
200 }
201
202 impl<T> private::Sealed for $name<T> {}
203 };
204
205 ($(($js:ident, $name:ident, $type:ty),)*) => {
206 $(typed_array!($js, $name, $type);)*
207 };
208}
209
210typed_array![
211 (JsInt8Array, Int8Array, i8),
212 (JsUint8Array, Uint8Array, u8),
213 (JsInt16Array, Int16Array, i16),
214 (JsUint16Array, Uint16Array, u16),
215 (JsInt32Array, Int32Array, i32),
216 (JsUint32Array, Uint32Array, u32),
217 (JsFloat32Array, Float32Array, f32),
218 (JsFloat64Array, Float64Array, f64),
219 (JsBigInt64Array, BigInt64Array, i64),
220 (JsBigUint64Array, BigUint64Array, u64),
221];