Skip to main content

kimchi_stubs/
field_vector.rs

1//! We implement a custom type for field vectors in order to quickly build field
2//! vectors from the OCaml side and avoid large vector clones.
3
4use paste::paste;
5
6macro_rules! impl_vector_old {
7    ($name: ident, $CamlF: ty, $F: ty) => {
8
9        impl_caml_pointer!($name => Vec<$F>);
10
11        paste! {
12            #[ocaml_gen::func]
13            #[ocaml::func]
14            pub fn [<$name:snake _create>]() -> $name {
15                $name::create(Vec::new())
16            }
17
18            #[ocaml_gen::func]
19            #[ocaml::func]
20            pub fn [<$name:snake _length>](v: $name) -> ocaml::Int {
21                v.len() as isize
22            }
23
24            #[ocaml_gen::func]
25            #[ocaml::func]
26            pub fn [<$name:snake _emplace_back>](mut v: $name, x: $CamlF) {
27                (*v).push(x.into());
28            }
29
30            // Empty the vector and release its backing allocation. OCaml only
31            // sees the pointer, so its GC never feels the (potentially large)
32            // Rust buffer; this lets a caller free it eagerly when done.
33            #[ocaml_gen::func]
34            #[ocaml::func]
35            pub fn [<$name:snake _clear>](mut v: $name) {
36                (*v).clear();
37                (*v).shrink_to_fit();
38            }
39
40            #[ocaml_gen::func]
41            #[ocaml::func]
42            pub fn [<$name:snake _get>](
43                v: $name,
44                i: ocaml::Int,
45            ) -> Result<$CamlF, ocaml::Error> {
46                match v.get(i as usize) {
47                    Some(x) => Ok(x.into()),
48                    None => Err(ocaml::Error::invalid_argument("vector_get")
49                        .err()
50                        .unwrap()),
51                }
52            }
53
54            #[ocaml_gen::func]
55            #[ocaml::func]
56            pub fn [<$name:snake _set>](
57                mut v: $name,
58                i: ocaml::Int,
59                value: $CamlF,
60            ) -> Result<(), ocaml::Error> {
61                match v.get_mut(i as usize) {
62                    Some(x) => Ok(*x = value.into()),
63                    None => Err(ocaml::Error::invalid_argument("vector_set")
64                        .err()
65                        .unwrap()),
66                }
67            }
68        }
69    };
70}
71
72#[allow(unused_macros)]
73macro_rules! impl_vector {
74    ($name: ident, $CamlF: ty, $F: ty) => {
75
76        impl_shared_rwlock!($name => Vec<$F>);
77
78        paste! {
79            #[ocaml_gen::func]
80            #[ocaml::func]
81            pub fn [<$name:snake _create>]() -> $name {
82                $name::new(Vec::new())
83            }
84
85            #[ocaml_gen::func]
86            #[ocaml::func]
87            pub fn [<$name:snake _length>](v: $name) -> Result<ocaml::Int, ocaml::Error> {
88                let v = v.read().map_err(|_| ocaml::CamlError::Failure("vector_length: could not capture lock"))?;
89                Ok(v.len() as isize)
90            }
91
92            #[ocaml_gen::func]
93            #[ocaml::func]
94            pub fn [<$name:snake _emplace_back>](v: $name, x: $CamlF) -> Result<(), ocaml::Error> {
95                let mut v = v.write().map_err(|_| ocaml::CamlError::Failure("vector_emplace_back: could not capture lock"))?;
96                v.push(x.into());
97                Ok(())
98            }
99
100            #[ocaml_gen::func]
101            #[ocaml::func]
102            pub fn [<$name:snake _get>](
103                v: $name,
104                i: ocaml::Int,
105            ) -> Result<$CamlF, ocaml::Error> {
106                let v = v.read().map_err(|_| ocaml::CamlError::Failure("vector_get: could not capture lock"))?;
107                match v.get(i as usize) {
108                    Some(x) => Ok(x.into()),
109                    None => Err(ocaml::Error::invalid_argument("vector_get")
110                        .err()
111                        .unwrap()),
112                }
113            }
114
115            #[ocaml_gen::func]
116            #[ocaml::func]
117            pub fn [<$name:snake _set>](
118                v: $name,
119                i: ocaml::Int,
120                value: $CamlF,
121            ) -> Result<(), ocaml::Error> {
122                let mut v = v.write().map_err(|_| ocaml::CamlError::Failure("vector_set: could not capture lock"))?;
123                match v.get_mut(i as usize) {
124                    Some(x) => Ok(*x = value.into()),
125                    None => Err(ocaml::Error::invalid_argument("vector_set")
126                        .err()
127                        .unwrap()),
128                }
129            }
130        }
131    }
132}
133
134pub mod fp {
135    use super::*;
136    use crate::arkworks::CamlFp;
137    use mina_curves::pasta::Fp;
138
139    impl_vector_old!(CamlFpVector, CamlFp, Fp);
140}
141
142pub mod fq {
143    use super::*;
144    use crate::arkworks::CamlFq;
145    use mina_curves::pasta::Fq;
146
147    impl_vector_old!(CamlFqVector, CamlFq, Fq);
148}