circom_lsp_program_structure/utils/
memory_slice.rs1use num_bigint_dig::BigInt;
2use std::fmt::{Display, Formatter};
3
4pub enum TypeInvalidAccess{
5 MissingInputs(String),
6 MissingInputTags(String),
7 NoInitializedComponent,
8 NoInitializedSignal
9}
10
11pub enum TypeAssignmentError{
12 MultipleAssignments,
13 AssignmentOutput
14}
15
16pub enum MemoryError {
17 OutOfBoundsError,
18 AssignmentError(TypeAssignmentError),
19 InvalidAccess(TypeInvalidAccess),
20 UnknownSizeDimension,
21 MismatchedDimensions(usize, usize),
22 MismatchedDimensionsWeak(usize, usize),
23 AssignmentMissingTags(String),
24 AssignmentTagAfterInit,
25 AssignmentTagTwice,
26 AssignmentTagInput,
27 TagValueNotInitializedAccess,
28 MissingInputs(String)
29}
30pub type SliceCapacity = usize;
31pub type SimpleSlice = MemorySlice<BigInt>;
32#[derive(Eq, PartialEq)]
38pub struct MemorySlice<C> {
39 route: Vec<SliceCapacity>,
40 values: Vec<C>,
41}
42
43impl<C: Clone> Clone for MemorySlice<C> {
44 fn clone(&self) -> Self {
45 MemorySlice { route: self.route.clone(), values: self.values.clone() }
46 }
47}
48
49impl<C: Default + Clone + Display + Eq> Display for MemorySlice<C> {
50 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
51 if self.values.is_empty() {
52 f.write_str("[]")
53 } else if self.values.len() == 1 {
54 f.write_str(&format!("{}", self.values[0]))
55 } else {
56 let mut msg = format!("[{}", self.values[0]);
57 for i in 1..self.values.len() {
58 msg.push_str(&format!(",{}", self.values[i]));
59 }
60 msg.push_str("]");
61 f.write_str(&msg)
62 }
63 }
64}
65
66impl<C: Clone> MemorySlice<C> {
67 fn get_initial_cell(
69 memory_slice: &MemorySlice<C>,
70 access: &[SliceCapacity],
71 ) -> Result<SliceCapacity, MemoryError> {
72
73 if access.len() > memory_slice.route.len() {
74 return Result::Err(MemoryError::OutOfBoundsError);
75 }
76
77 let mut cell = 0;
78 let mut cell_jump = memory_slice.values.len();
79 let mut i: SliceCapacity = 0;
80 while i < access.len() {
81 if access[i] >= memory_slice.route[i] {
82 return Result::Err(MemoryError::OutOfBoundsError);
83 }
84 cell_jump /= memory_slice.route[i];
85 cell += cell_jump * access[i];
86 i += 1;
87 }
88 Result::Ok(cell)
89 }
90 pub fn check_correct_dims(
91 memory_slice: &MemorySlice<C>,
92 access: &[SliceCapacity],
93 new_values: &MemorySlice<C>,
94 is_strict: bool,
95 ) -> Result<(), MemoryError> {
96
97 if access.len() + new_values.route.len() > memory_slice.route.len() {
98 return Result::Err(MemoryError::OutOfBoundsError);
99 }
100
101 let mut i: SliceCapacity = 0;
102
103 while i < access.len() {
104 if access[i] >= memory_slice.route[i] {
105 return Result::Err(MemoryError::OutOfBoundsError);
106 }
107 i += 1;
108 }
109
110 let initial_index_new: SliceCapacity = i;
111 i = 0;
112
113 while i < new_values.route.len() {
114 if new_values.route[i] < memory_slice.route[initial_index_new + i] {
115 if is_strict{ return Result::Err(MemoryError::MismatchedDimensions(new_values.route[i], memory_slice.route[initial_index_new + i]));
117 } else{ return Result::Err(MemoryError::MismatchedDimensionsWeak(new_values.route[i], memory_slice.route[initial_index_new + i]));
119 }
120 }
121 if new_values.route[i] > memory_slice.route[initial_index_new + i] {
122 return Result::Err(MemoryError::MismatchedDimensions(new_values.route[i], memory_slice.route[initial_index_new + i]));
123 }
124 i += 1;
125 }
126 Result::Ok(())
127 }
128
129 fn generate_new_route_from_access(
132 memory_slice: &MemorySlice<C>,
133 access: &[SliceCapacity],
134 ) -> Result<(Vec<SliceCapacity>, SliceCapacity), MemoryError> {
135 if access.len() > memory_slice.route.len() {
136 return Result::Err(MemoryError::OutOfBoundsError);
137 }
138
139 let mut size = Vec::new();
140 let mut number_of_cells = 1;
141 for i in access.len()..memory_slice.route.len() {
142 number_of_cells *= memory_slice.route[i];
143 size.push(memory_slice.route[i]);
144 }
145 Result::Ok((size, number_of_cells))
146 }
147
148 fn generate_slice_from_access(
149 memory_slice: &MemorySlice<C>,
150 access: &[SliceCapacity],
151 ) -> Result<MemorySlice<C>, MemoryError> {
152 if access.is_empty() {
153 return Result::Ok(memory_slice.clone());
154 }
155
156 let (size, number_of_cells) =
157 MemorySlice::generate_new_route_from_access(memory_slice, access)?;
158 let mut values = Vec::with_capacity(number_of_cells);
159 let initial_cell = MemorySlice::get_initial_cell(memory_slice, access)?;
160 let mut offset = 0;
161 while offset < number_of_cells {
162 let new_value = memory_slice.values[initial_cell + offset].clone();
163 values.push(new_value);
164 offset += 1;
165 }
166
167 Result::Ok(MemorySlice { route: size, values })
168 }
169
170 pub fn new(initial_value: &C) -> MemorySlice<C> {
172 MemorySlice::new_with_route(&[], initial_value)
173 }
174 pub fn new_array(route: Vec<SliceCapacity>, values: Vec<C>) -> MemorySlice<C> {
175 MemorySlice { route, values }
176 }
177 pub fn new_with_route(route: &[SliceCapacity], initial_value: &C) -> MemorySlice<C> {
178 let mut length = 1;
179 for i in route {
180 length *= *i;
181 }
182
183 let mut values = Vec::with_capacity(length);
184 for _i in 0..length {
185 values.push(initial_value.clone());
186 }
187
188 MemorySlice { route: route.to_vec(), values }
189 }
190 pub fn insert_values(
191 memory_slice: &mut MemorySlice<C>,
192 access: &[SliceCapacity],
193 new_values: &MemorySlice<C>,
194 is_strict:bool,
195 ) -> Result<(), MemoryError> {
196 match MemorySlice::check_correct_dims(memory_slice, access, new_values, is_strict){
197 Result::Ok(_) => {
198 let mut cell = MemorySlice::get_initial_cell(memory_slice, access)?;
199
200 for value in new_values.values.iter() {
206 memory_slice.values[cell] = value.clone();
207 cell += 1;
208 }
209 Result::Ok(())
210 },
211 Result::Err(MemoryError::MismatchedDimensionsWeak(dim_1, dim_2)) => {
212 let mut cell = MemorySlice::get_initial_cell(memory_slice, access)?;
213 for value in new_values.values.iter() {
219 memory_slice.values[cell] = value.clone();
220 cell += 1;
221 }
222 Result::Err(MemoryError::MismatchedDimensionsWeak(dim_1, dim_2))
223 },
224 Result::Err(error) => return Err(error),
225 }
226 }
227
228 pub fn insert_value_by_index(
229 memory_slice: &mut MemorySlice<C>,
230 index: usize,
231 new_value: C,
232 )-> Result<(), MemoryError> {
233 if index > MemorySlice::get_number_of_cells(memory_slice) {
234 return Result::Err(MemoryError::OutOfBoundsError);
235 }
236 memory_slice.values[index] = new_value;
237 return Result::Ok(());
238 }
239
240 pub fn get_access_index(
241 memory_slice: &MemorySlice<C>,
242 index: usize,
243 ) -> Result<Vec<SliceCapacity>, MemoryError>{
244 let mut number_cells = MemorySlice::get_number_of_cells(memory_slice);
245 if index > number_cells {
246 return Result::Err(MemoryError::OutOfBoundsError);
247 }
248 else{
249 let mut access = vec![];
250 let mut index_aux = index;
251 for pos in &memory_slice.route{
252 number_cells = number_cells/pos;
253 access.push(index_aux / number_cells);
254 index_aux = index_aux % number_cells;
255 }
256 return Result::Ok(access);
257 }
258 }
259
260 pub fn access_values(
261 memory_slice: &MemorySlice<C>,
262 access: &[SliceCapacity],
263 ) -> Result<MemorySlice<C>, MemoryError> {
264 MemorySlice::generate_slice_from_access(memory_slice, access)
265 }
266 pub fn access_value_by_index(
267 memory_slice: &MemorySlice<C>,
268 index: usize,
269 )-> Result<C, MemoryError> {
270 if index > MemorySlice::get_number_of_cells(memory_slice) {
271 return Result::Err(MemoryError::OutOfBoundsError);
272 }
273 return Result::Ok(memory_slice.values[index].clone());
274 }
275
276 pub fn get_reference_to_single_value<'a>(
277 memory_slice: &'a MemorySlice<C>,
278 access: &[SliceCapacity],
279 ) -> Result<&'a C, MemoryError> {
280 assert_eq!(memory_slice.route.len(), access.len());
281 let cell = MemorySlice::get_initial_cell(memory_slice, access)?;
282 Result::Ok(&memory_slice.values[cell])
283 }
284 pub fn get_reference_to_single_value_by_index<'a>(
285 memory_slice: &'a MemorySlice<C>,
286 index: usize,
287 ) -> Result<&'a C, MemoryError> {
288 if index > MemorySlice::get_number_of_cells(memory_slice) {
289 return Result::Err(MemoryError::OutOfBoundsError);
290 }
291 Result::Ok(&memory_slice.values[index])
292 }
293 pub fn get_reference_to_single_value_by_index_or_break<'a>(
294 memory_slice: &'a MemorySlice<C>,
295 index: usize,
296 ) -> &'a C {
297 if index > MemorySlice::get_number_of_cells(memory_slice) {
298 unreachable!("The index is too big for the slice");
299 }
300 &memory_slice.values[index]
301 }
302 pub fn get_mut_reference_to_single_value<'a>(
303 memory_slice: &'a mut MemorySlice<C>,
304 access: &[SliceCapacity],
305 ) -> Result<&'a mut C, MemoryError> {
306 assert_eq!(memory_slice.route.len(), access.len());
307 let cell = MemorySlice::get_initial_cell(memory_slice, access)?;
308 Result::Ok(&mut memory_slice.values[cell])
309 }
310 pub fn get_number_of_cells(memory_slice: &MemorySlice<C>) -> SliceCapacity {
311 memory_slice.values.len()
312 }
313 pub fn route(&self) -> &[SliceCapacity] {
314 &self.route
315 }
316 pub fn is_single(&self) -> bool {
317 self.route.is_empty()
318 }
319 pub fn unwrap_to_single(memory_slice: MemorySlice<C>) -> C {
327 assert!(memory_slice.is_single());
328 let mut memory_slice = memory_slice;
329 memory_slice.values.pop().unwrap()
330 }
331 pub fn destruct(self) -> (Vec<SliceCapacity>, Vec<C>) {
332 (self.route, self.values)
333 }
334}
335
336#[cfg(test)]
337mod tests {
338 use super::*;
339 type U32Slice = MemorySlice<u32>;
340
341 #[test]
342 fn memory_slice_vector_initialization() {
343 let route = vec![3, 4];
344 let slice = U32Slice::new_with_route(&route, &0);
345 assert_eq!(U32Slice::get_number_of_cells(&slice), 12);
346 for (dim_0, dim_1) in slice.route.iter().zip(&route) {
347 assert_eq!(*dim_0, *dim_1);
348 }
349 for f in 0..3 {
350 for c in 0..4 {
351 let result = U32Slice::get_reference_to_single_value(&slice, &[f, c]);
352 if let Result::Ok(v) = result {
353 assert_eq!(*v, 0);
354 } else {
355 assert!(false);
356 }
357 }
358 }
359 }
360 #[test]
361 fn memory_slice_single_initialization() {
362 let slice = U32Slice::new(&4);
363 assert_eq!(U32Slice::get_number_of_cells(&slice), 1);
364 let memory_response = U32Slice::get_reference_to_single_value(&slice, &[]);
365 if let Result::Ok(val) = memory_response {
366 assert_eq!(*val, 4);
367 } else {
368 assert!(false);
369 }
370 }
371 #[test]
372 fn memory_slice_multiple_insertion() {
373 let route = vec![3, 4];
374 let mut slice = U32Slice::new_with_route(&route, &0);
375 let new_row = U32Slice::new_with_route(&[4], &4);
376
377 let res = U32Slice::insert_values(&mut slice, &[2], &new_row);
378 if let Result::Ok(_) = res {
379 for c in 0..4 {
380 let memory_result = U32Slice::get_reference_to_single_value(&slice, &[2, c]);
381 if let Result::Ok(val) = memory_result {
382 assert_eq!(*val, 4);
383 } else {
384 assert!(false);
385 }
386 }
387 } else {
388 assert!(false);
389 }
390 }
391}