Skip to main content

kimchi_napi/
vector.rs

1use napi::{bindgen_prelude::*, sys};
2use serde::{Deserialize, Serialize};
3use std::{iter::FromIterator, ops::Deref};
4use wasm_types::{FlatVector, FlatVectorElem};
5
6#[derive(Clone, Debug, Default)]
7pub struct NapiFlatVector<T>(pub Vec<T>);
8
9impl<T> NapiFlatVector<T> {
10    pub fn into_inner(self) -> Vec<T> {
11        self.0
12    }
13}
14
15impl<T: FlatVectorElem> NapiFlatVector<T> {
16    pub fn from_bytes(bytes: Vec<u8>) -> Self {
17        let flat: FlatVector<T> = FlatVector::from_bytes(bytes);
18        NapiFlatVector(flat.into())
19    }
20
21    pub fn into_bytes(self) -> Vec<u8> {
22        self.0
23            .into_iter()
24            .flat_map(FlatVectorElem::flatten)
25            .collect()
26    }
27}
28
29impl<T> Deref for NapiFlatVector<T> {
30    type Target = Vec<T>;
31
32    fn deref(&self) -> &Self::Target {
33        &self.0
34    }
35}
36
37impl<T> From<Vec<T>> for NapiFlatVector<T> {
38    fn from(value: Vec<T>) -> Self {
39        NapiFlatVector(value)
40    }
41}
42
43impl<T> From<NapiFlatVector<T>> for Vec<T> {
44    fn from(value: NapiFlatVector<T>) -> Self {
45        value.0
46    }
47}
48
49impl<T> From<FlatVector<T>> for NapiFlatVector<T> {
50    fn from(value: FlatVector<T>) -> Self {
51        NapiFlatVector(value.into())
52    }
53}
54
55impl<T> From<NapiFlatVector<T>> for FlatVector<T> {
56    fn from(value: NapiFlatVector<T>) -> Self {
57        FlatVector::from(value.0)
58    }
59}
60
61impl<'a, T> From<&'a NapiFlatVector<T>> for &'a Vec<T> {
62    fn from(value: &'a NapiFlatVector<T>) -> Self {
63        &value.0
64    }
65}
66
67impl<T> IntoIterator for NapiFlatVector<T> {
68    type Item = T;
69    type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
70
71    fn into_iter(self) -> Self::IntoIter {
72        self.0.into_iter()
73    }
74}
75
76impl<'a, T> IntoIterator for &'a NapiFlatVector<T> {
77    type Item = &'a T;
78    type IntoIter = <&'a Vec<T> as IntoIterator>::IntoIter;
79
80    fn into_iter(self) -> Self::IntoIter {
81        self.0.iter()
82    }
83}
84
85impl<T> FromIterator<T> for NapiFlatVector<T> {
86    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
87        NapiFlatVector(Vec::from_iter(iter))
88    }
89}
90
91impl<T> Extend<T> for NapiFlatVector<T> {
92    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
93        self.0.extend(iter);
94    }
95}
96
97impl<T> TypeName for NapiFlatVector<T>
98where
99    Vec<u8>: TypeName,
100{
101    fn type_name() -> &'static str {
102        <Vec<u8> as TypeName>::type_name()
103    }
104
105    fn value_type() -> ValueType {
106        <Vec<u8> as TypeName>::value_type()
107    }
108}
109
110impl<T> ValidateNapiValue for NapiFlatVector<T>
111where
112    Vec<u8>: ValidateNapiValue,
113    Uint8Array: ValidateNapiValue,
114{
115    unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
116        // Accept both `Uint8Array`/`Buffer` and `number[]` so JS callers can pass either
117        // a typed array (preferred) or an array of bytes.
118        if <Uint8Array as ValidateNapiValue>::validate(env, napi_val).is_ok() {
119            return Ok(napi_val);
120        }
121        <Vec<u8> as ValidateNapiValue>::validate(env, napi_val)
122    }
123}
124
125impl<T> FromNapiValue for NapiFlatVector<T>
126where
127    T: FlatVectorElem,
128{
129    unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
130        // Prefer `Uint8Array`/`Buffer` inputs for performance.
131        let bytes = if let Ok(arr) = <Uint8Array as FromNapiValue>::from_napi_value(env, napi_val) {
132            arr.as_ref().to_vec()
133        } else {
134            <Vec<u8> as FromNapiValue>::from_napi_value(env, napi_val)?
135        };
136        Ok(NapiFlatVector::from_bytes(bytes))
137    }
138}
139
140impl<T> ToNapiValue for NapiFlatVector<T>
141where
142    T: FlatVectorElem,
143{
144    unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
145        let bytes = val.into_bytes();
146        <Uint8Array as ToNapiValue>::to_napi_value(env, Uint8Array::from(bytes))
147    }
148}
149
150impl<T> ToNapiValue for &NapiFlatVector<T>
151where
152    T: FlatVectorElem + Clone,
153{
154    unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
155        let bytes = val
156            .0
157            .clone()
158            .into_iter()
159            .flat_map(FlatVectorElem::flatten)
160            .collect::<Vec<_>>();
161        <Uint8Array as ToNapiValue>::to_napi_value(env, Uint8Array::from(bytes))
162    }
163}
164
165impl<T> ToNapiValue for &mut NapiFlatVector<T>
166where
167    T: FlatVectorElem + Clone,
168{
169    unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
170        let bytes = val
171            .0
172            .clone()
173            .into_iter()
174            .flat_map(FlatVectorElem::flatten)
175            .collect::<Vec<_>>();
176        <Uint8Array as ToNapiValue>::to_napi_value(env, Uint8Array::from(bytes))
177    }
178}
179
180#[derive(Clone, Debug, Serialize, Deserialize, Default)]
181pub struct NapiVector<T>(pub Vec<T>);
182
183impl<T> NapiVector<T> {
184    pub fn into_inner(self) -> Vec<T> {
185        self.0
186    }
187}
188
189impl<T> Deref for NapiVector<T> {
190    type Target = Vec<T>;
191
192    fn deref(&self) -> &Self::Target {
193        &self.0
194    }
195}
196
197impl<T> From<Vec<T>> for NapiVector<T> {
198    fn from(value: Vec<T>) -> Self {
199        NapiVector(value)
200    }
201}
202
203impl<T> From<NapiVector<T>> for Vec<T> {
204    fn from(value: NapiVector<T>) -> Self {
205        value.0
206    }
207}
208
209impl<'a, T> From<&'a NapiVector<T>> for &'a Vec<T> {
210    fn from(value: &'a NapiVector<T>) -> Self {
211        &value.0
212    }
213}
214
215impl<T> IntoIterator for NapiVector<T> {
216    type Item = T;
217    type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
218
219    fn into_iter(self) -> Self::IntoIter {
220        self.0.into_iter()
221    }
222}
223
224impl<'a, T> IntoIterator for &'a NapiVector<T> {
225    type Item = &'a T;
226    type IntoIter = <&'a Vec<T> as IntoIterator>::IntoIter;
227
228    fn into_iter(self) -> Self::IntoIter {
229        self.0.iter()
230    }
231}
232
233impl<T> FromIterator<T> for NapiVector<T> {
234    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
235        NapiVector(Vec::from_iter(iter))
236    }
237}
238
239impl<T> Extend<T> for NapiVector<T> {
240    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
241        self.0.extend(iter);
242    }
243}
244
245impl<T> TypeName for NapiVector<T>
246where
247    Vec<T>: TypeName,
248{
249    fn type_name() -> &'static str {
250        <Vec<T> as TypeName>::type_name()
251    }
252
253    fn value_type() -> ValueType {
254        <Vec<T> as TypeName>::value_type()
255    }
256}
257
258impl<T> ValidateNapiValue for NapiVector<T>
259where
260    Vec<T>: ValidateNapiValue,
261    T: FromNapiValue,
262{
263    unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
264        <Vec<T> as ValidateNapiValue>::validate(env, napi_val)
265    }
266}
267
268impl<T> FromNapiValue for NapiVector<T>
269where
270    Vec<T>: FromNapiValue,
271{
272    unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
273        Ok(NapiVector(<Vec<T> as FromNapiValue>::from_napi_value(
274            env, napi_val,
275        )?))
276    }
277}
278
279impl<T> ToNapiValue for NapiVector<T>
280where
281    Vec<T>: ToNapiValue,
282{
283    unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
284        <Vec<T> as ToNapiValue>::to_napi_value(env, val.0)
285    }
286}
287
288impl<T> ToNapiValue for &NapiVector<T>
289where
290    Vec<T>: ToNapiValue,
291    T: Clone,
292{
293    unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
294        let cloned: Vec<T> = val.0.clone();
295        <Vec<T> as ToNapiValue>::to_napi_value(env, cloned)
296    }
297}
298
299impl<T> ToNapiValue for &mut NapiVector<T>
300where
301    Vec<T>: ToNapiValue,
302    T: Clone,
303{
304    unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
305        let cloned: Vec<T> = val.0.clone();
306        <Vec<T> as ToNapiValue>::to_napi_value(env, cloned)
307    }
308}
309
310macro_rules! impl_vec_vec {
311    ($name:ident, $field:ty, $napi_field:ty, $wasm_vec_vec:literal) => {
312        #[napi(js_name = $wasm_vec_vec)]
313        #[derive(Clone, Debug, Default)]
314        pub struct $name(#[napi(skip)] pub Vec<Vec<$field>>);
315
316        #[napi]
317        impl $name {
318            #[napi(constructor)]
319            pub fn new(capacity: i32) -> Self {
320                $name(Vec::with_capacity(capacity as usize))
321            }
322
323            #[napi]
324            pub fn push(&mut self, vector: Uint8Array) -> Result<()> {
325                let flattened = vector.as_ref().to_vec();
326                let values = FlatVector::<$napi_field>::from_bytes(flattened)
327                    .into_iter()
328                    .map(Into::into)
329                    .collect();
330                self.0.push(values);
331                Ok(())
332            }
333
334            #[napi]
335            pub fn get(&self, index: i32) -> Result<Uint8Array> {
336                let slice = self.0.get(index as usize).ok_or_else(|| {
337                    Error::new(Status::InvalidArg, "index out of bounds".to_string())
338                })?;
339
340                let bytes = slice
341                    .iter()
342                    .cloned()
343                    .map(<$napi_field>::from)
344                    .flat_map(FlatVectorElem::flatten)
345                    .collect::<Vec<u8>>();
346
347                Ok(Uint8Array::from(bytes))
348            }
349
350            #[napi]
351            pub fn set(&mut self, index: i32, vector: Uint8Array) -> Result<()> {
352                let entry = self.0.get_mut(index as usize).ok_or_else(|| {
353                    Error::new(Status::InvalidArg, "index out of bounds".to_string())
354                })?;
355
356                let flattened = vector.as_ref().to_vec();
357                *entry = FlatVector::<$napi_field>::from_bytes(flattened)
358                    .into_iter()
359                    .map(Into::into)
360                    .collect();
361                Ok(())
362            }
363        }
364
365        impl FromNapiValue for $name {
366            unsafe fn from_napi_value(
367                env: sys::napi_env,
368                napi_val: sys::napi_value,
369            ) -> Result<Self> {
370                let instance =
371                    <ClassInstance<$name> as FromNapiValue>::from_napi_value(env, napi_val)?;
372                Ok((*instance).clone())
373            }
374        }
375
376        impl From<Vec<Vec<$field>>> for $name {
377            fn from(value: Vec<Vec<$field>>) -> Self {
378                Self(value)
379            }
380        }
381
382        impl From<$name> for Vec<Vec<$field>> {
383            fn from(value: $name) -> Self {
384                value.0
385            }
386        }
387    };
388}
389
390pub mod fp {
391    use super::*;
392    use crate::wrappers::field::NapiPastaFp;
393    use mina_curves::pasta::Fp;
394    use napi_derive::napi;
395
396    impl_vec_vec!(NapiVecVecFp, Fp, NapiPastaFp, "WasmVecVecFp");
397}
398
399pub mod fq {
400    use super::*;
401    use crate::wrappers::field::NapiPastaFq;
402    use mina_curves::pasta::Fq;
403    use napi_derive::napi;
404
405    impl_vec_vec!(NapiVecVecFq, Fq, NapiPastaFq, "WasmVecVecFq");
406}