1use crate::stdlib::collections::HashSet;
2use core::cmp::max;
3use core::fmt;
4
5use crate::vm::runners::cairo_pie::CairoPieMemory;
6use crate::Felt252;
7use num_traits::Zero;
8
9use crate::stdlib::prelude::*;
10use crate::stdlib::{any::Any, collections::HashMap};
11use crate::vm::runners::cairo_runner::CairoArg;
12
13use crate::{
14 types::relocatable::{MaybeRelocatable, Relocatable},
15 vm::{
16 errors::memory_errors::MemoryError, errors::vm_errors::VirtualMachineError,
17 vm_memory::memory::Memory,
18 },
19};
20
21use super::memory::MemoryCell;
22
23pub struct MemorySegmentManager {
24 pub segment_sizes: HashMap<usize, usize>,
25 pub segment_used_sizes: Option<Vec<usize>>,
26 pub memory: Memory,
27 pub public_memory_offsets: HashMap<usize, Vec<(usize, usize)>>,
30 zero_segment_index: usize,
33 zero_segment_size: usize,
35}
36
37impl MemorySegmentManager {
38 pub fn num_segments(&self) -> usize {
40 self.memory.data.len()
41 }
42
43 pub fn num_temp_segments(&self) -> usize {
45 self.memory.temp_data.len()
46 }
47
48 pub fn add(&mut self) -> Relocatable {
50 self.memory.data.push(Vec::new());
51 Relocatable {
52 segment_index: (self.memory.data.len() - 1) as isize,
53 offset: 0,
54 }
55 }
56
57 pub fn add_temporary_segment(&mut self) -> Relocatable {
59 self.memory.temp_data.push(Vec::new());
60 Relocatable {
61 segment_index: -((self.memory.temp_data.len()) as isize),
63 offset: 0,
64 }
65 }
66
67 pub fn load_data(
69 &mut self,
70 ptr: Relocatable,
71 data: &[MaybeRelocatable],
72 ) -> Result<Relocatable, MemoryError> {
73 for (num, value) in data.iter().enumerate().rev() {
76 self.memory.insert((ptr + num)?, value)?;
77 }
78 (ptr + data.len()).map_err(MemoryError::Math)
79 }
80
81 pub fn new() -> MemorySegmentManager {
82 MemorySegmentManager {
83 segment_sizes: HashMap::new(),
84 segment_used_sizes: None,
85 public_memory_offsets: HashMap::new(),
86 memory: Memory::new(),
87 zero_segment_index: 0,
88 zero_segment_size: 0,
89 }
90 }
91
92 pub fn compute_effective_sizes(&mut self) -> &Vec<usize> {
94 self.segment_used_sizes
95 .get_or_insert_with(|| self.memory.data.iter().map(Vec::len).collect())
96 }
97
98 pub fn get_segment_used_size(&self, index: usize) -> Option<usize> {
101 self.segment_used_sizes.as_ref()?.get(index).copied()
102 }
103
104 pub fn get_segment_size(&self, index: usize) -> Option<usize> {
105 self.segment_sizes
106 .get(&index)
107 .cloned()
108 .or_else(|| self.get_segment_used_size(index))
109 }
110
111 pub fn relocate_segments(&self) -> Result<Vec<usize>, MemoryError> {
113 let first_addr = 1;
114 let mut relocation_table = vec![first_addr];
115 match &self.segment_used_sizes {
116 Some(segment_used_sizes) => {
117 for (i, _size) in segment_used_sizes.iter().enumerate() {
118 let segment_size = self
119 .get_segment_size(i)
120 .ok_or(MemoryError::MissingSegmentUsedSizes)?;
121
122 relocation_table.push(relocation_table[i] + segment_size);
123 }
124 }
125 None => return Err(MemoryError::MissingSegmentUsedSizes),
126 }
127 relocation_table.pop();
129 Ok(relocation_table)
130 }
131
132 pub fn gen_arg(&mut self, arg: &dyn Any) -> Result<MaybeRelocatable, MemoryError> {
133 if let Some(value) = arg.downcast_ref::<MaybeRelocatable>() {
134 Ok(value.clone())
135 } else if let Some(value) = arg.downcast_ref::<Vec<MaybeRelocatable>>() {
136 let base = self.add();
137 self.write_arg(base, value)?;
138 Ok(base.into())
139 } else if let Some(value) = arg.downcast_ref::<Vec<Relocatable>>() {
140 let base = self.add();
141 self.write_arg(base, value)?;
142 Ok(base.into())
143 } else {
144 Err(MemoryError::GenArgInvalidType)
145 }
146 }
147
148 pub fn gen_cairo_arg(
149 &mut self,
150 arg: &CairoArg,
151 ) -> Result<MaybeRelocatable, VirtualMachineError> {
152 match arg {
153 CairoArg::Single(value) => Ok(value.clone()),
154 CairoArg::Array(values) => {
155 let base = self.add();
156 self.load_data(base, values)?;
157 Ok(base.into())
158 }
159 CairoArg::Composed(cairo_args) => {
160 let args = cairo_args
161 .iter()
162 .map(|cairo_arg| self.gen_cairo_arg(cairo_arg))
163 .collect::<Result<Vec<MaybeRelocatable>, VirtualMachineError>>()?;
164 let base = self.add();
165 self.load_data(base, &args)?;
166 Ok(base.into())
167 }
168 }
169 }
170
171 pub fn write_arg(
172 &mut self,
173 ptr: Relocatable,
174 arg: &dyn Any,
175 ) -> Result<MaybeRelocatable, MemoryError> {
176 if let Some(vector) = arg.downcast_ref::<Vec<MaybeRelocatable>>() {
177 self.load_data(ptr, vector).map(Into::into)
178 } else if let Some(vector) = arg.downcast_ref::<Vec<Relocatable>>() {
179 let data: &Vec<MaybeRelocatable> = &vector.iter().map(|value| value.into()).collect();
180 self.load_data(ptr, data).map(Into::into)
181 } else {
182 Err(MemoryError::WriteArg)
183 }
184 }
185
186 pub fn is_valid_memory_value(&self, value: &MaybeRelocatable) -> Result<bool, MemoryError> {
187 match &self.segment_used_sizes {
188 Some(segment_used_sizes) => match value {
189 MaybeRelocatable::Int(_) => Ok(true),
190 MaybeRelocatable::RelocatableValue(relocatable) => {
191 let segment_index: usize =
192 relocatable.segment_index.try_into().map_err(|_| {
193 MemoryError::AddressInTemporarySegment(relocatable.segment_index)
194 })?;
195
196 Ok(segment_index < segment_used_sizes.len())
197 }
198 },
199 None => Err(MemoryError::MissingSegmentUsedSizes),
200 }
201 }
202
203 pub fn is_accessed(&self, addr: &Relocatable) -> Result<bool, MemoryError> {
204 self.memory.is_accessed(addr)
205 }
206
207 pub fn get_memory_holes(
211 &self,
212 builtin_segment_indexes: HashSet<usize>,
213 ) -> Result<usize, MemoryError> {
214 let data = &self.memory.data;
215 let mut memory_holes = 0;
216 for i in 0..data.len() {
217 if builtin_segment_indexes.contains(&i) {
220 continue;
221 }
222 let accessed_amount =
223 if self.has_zero_segment() && i == self.zero_segment_index {
225 self.zero_segment_size
226 } else {
227 match self.memory.get_amount_of_accessed_addresses_for_segment(i) {
228 Some(accessed_amount) if accessed_amount > 0 => accessed_amount,
229 _ => continue,
230 }
231 };
232 let segment_size = self
233 .get_segment_size(i)
234 .ok_or(MemoryError::MissingSegmentUsedSizes)?;
235 if accessed_amount > segment_size {
236 return Err(MemoryError::SegmentHasMoreAccessedAddressesThanSize(
237 Box::new((i, accessed_amount, segment_size)),
238 ));
239 }
240 memory_holes += segment_size - accessed_amount;
241 }
242 Ok(memory_holes)
243 }
244
245 pub fn get_public_memory_addresses(
248 &self,
249 segment_offsets: &[usize],
250 ) -> Result<Vec<(usize, usize)>, MemoryError> {
251 let mut addresses = Vec::with_capacity(self.num_segments());
252 let empty_vec = vec![];
253 for segment_index in 0..self.num_segments() {
254 let offsets = &self
255 .public_memory_offsets
256 .get(&segment_index)
257 .unwrap_or(&empty_vec);
258 let segment_start = segment_offsets
259 .get(segment_index)
260 .ok_or(MemoryError::MalformedPublicMemory)?;
261 for (offset, page_id) in offsets.iter() {
262 addresses.push((segment_start + offset, *page_id));
263 }
264 }
265 Ok(addresses)
266 }
267
268 pub fn finalize(
273 &mut self,
274 size: Option<usize>,
275 segment_index: usize,
276 public_memory: Option<&Vec<(usize, usize)>>,
277 ) {
278 if let Some(size) = size {
279 self.segment_sizes.insert(segment_index, size);
280 }
281 self.public_memory_offsets
282 .insert(segment_index, public_memory.cloned().unwrap_or_default());
283 }
284
285 pub fn has_zero_segment(&self) -> bool {
286 !self.zero_segment_index.is_zero()
287 }
288
289 pub(crate) fn add_zero_segment(&mut self, size: usize) -> usize {
293 if !self.has_zero_segment() {
294 self.zero_segment_index = self.add().segment_index as usize;
295 }
296
297 for _ in 0..(size.saturating_sub(self.zero_segment_size)) {
299 self.memory.data[self.zero_segment_index].push(MemoryCell::new(Felt252::ZERO.into()))
302 }
303 self.zero_segment_size = max(self.zero_segment_size, size);
304 self.zero_segment_index
305 }
306
307 pub(crate) fn finalize_zero_segment(&mut self) {
309 if self.has_zero_segment() {
310 self.finalize(Some(self.zero_segment_size), self.zero_segment_index, None);
311 self.zero_segment_index = 0;
312 self.zero_segment_size = 0;
313 }
314 }
315
316 pub(crate) fn load_pie_memory(
317 &mut self,
318 pie_memory: &CairoPieMemory,
319 n_extra_segments: usize,
320 ) -> Result<(), MemoryError> {
321 for _ in 0..n_extra_segments {
323 self.add();
324 }
325 for ((si, so), val) in pie_memory.0.iter() {
327 self.memory.insert((*si as isize, *so).into(), val)?;
328 }
329 Ok(())
330 }
331}
332
333impl Default for MemorySegmentManager {
334 fn default() -> Self {
335 Self::new()
336 }
337}
338
339impl fmt::Display for MemorySegmentManager {
340 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
341 writeln!(f, "Memory:\n{}", self.memory)?;
342 if let Some(used_sizes) = &self.segment_used_sizes {
343 writeln!(f, "Segment Info:")?;
344 for (index, used_size) in used_sizes.iter().enumerate() {
345 writeln!(
346 f,
347 "Segment Number: {}, Used Size: {}, Size {}",
348 index,
349 used_size,
350 self.segment_sizes
351 .get(&index)
352 .map(|n| n.to_string())
353 .unwrap_or(String::from("None"))
354 )?;
355 }
356 }
357 Ok(())
358 }
359}
360
361#[cfg(test)]
362mod tests {
363 use super::*;
364 use crate::Felt252;
365 use crate::{relocatable, utils::test_utils::*, vm::vm_memory::memory::MemoryCell};
366 use assert_matches::assert_matches;
367
368 #[cfg(target_arch = "wasm32")]
369 use wasm_bindgen_test::*;
370
371 #[test]
372 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
373 fn add_segment_no_size() {
374 let mut segments = MemorySegmentManager::new();
375 let base = segments.add();
376 assert_eq!(base, relocatable!(0, 0));
377 assert_eq!(segments.num_segments(), 1);
378 }
379
380 #[test]
381 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
382 fn add_segment_no_size_test_two_segments() {
383 let mut segments = MemorySegmentManager::new();
384 let mut _base = segments.add();
385 _base = segments.add();
386 assert_eq!(
387 _base,
388 Relocatable {
389 segment_index: 1,
390 offset: 0
391 }
392 );
393 assert_eq!(segments.num_segments(), 2);
394 }
395
396 #[test]
397 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
398 fn add_one_temporary_segment() {
399 let mut segments = MemorySegmentManager::new();
400 let base = segments.add_temporary_segment();
401 assert_eq!(base, relocatable!(-1, 0));
402 assert_eq!(segments.num_temp_segments(), 1);
403 }
404
405 #[test]
406 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
407 fn add_two_temporary_segments() {
408 let mut segments = MemorySegmentManager::new();
409 segments.add_temporary_segment();
410 let base = segments.add_temporary_segment();
411 assert_eq!(
412 base,
413 Relocatable {
414 segment_index: -2,
415 offset: 0
416 }
417 );
418 assert_eq!(segments.num_temp_segments(), 2);
419 }
420
421 #[test]
422 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
423 fn load_data_empty() {
424 let data = Vec::new();
425 let ptr = Relocatable::from((0, 3));
426 let mut segments = MemorySegmentManager::new();
427 let current_ptr = segments.load_data(ptr, &data).unwrap();
428 assert_eq!(current_ptr, Relocatable::from((0, 3)));
429 }
430
431 #[test]
432 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
433 fn load_data_one_element() {
434 let data = vec![MaybeRelocatable::from(Felt252::from(4))];
435 let ptr = Relocatable::from((0, 0));
436 let mut segments = MemorySegmentManager::new();
437 segments.add();
438 let current_ptr = segments.load_data(ptr, &data).unwrap();
439 assert_eq!(current_ptr, Relocatable::from((0, 1)));
440 assert_eq!(
441 segments.memory.get(&ptr).unwrap().as_ref(),
442 &MaybeRelocatable::from(Felt252::from(4))
443 );
444 }
445
446 #[test]
447 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
448 fn load_data_three_elements() {
449 let data = vec![
450 MaybeRelocatable::from(Felt252::from(4)),
451 MaybeRelocatable::from(Felt252::from(5)),
452 MaybeRelocatable::from(Felt252::from(6)),
453 ];
454 let ptr = Relocatable::from((0, 0));
455 let mut segments = MemorySegmentManager::new();
456 segments.add();
457 let current_ptr = segments.load_data(ptr, &data).unwrap();
458 assert_eq!(current_ptr, Relocatable::from((0, 3)));
459
460 assert_eq!(
461 segments.memory.get(&ptr).unwrap().as_ref(),
462 &MaybeRelocatable::from(Felt252::from(4))
463 );
464 assert_eq!(
465 segments
466 .memory
467 .get(&MaybeRelocatable::from((0, 1)))
468 .unwrap()
469 .as_ref(),
470 &MaybeRelocatable::from(Felt252::from(5))
471 );
472 assert_eq!(
473 segments
474 .memory
475 .get(&MaybeRelocatable::from((0, 2)))
476 .unwrap()
477 .as_ref(),
478 &MaybeRelocatable::from(Felt252::from(6))
479 );
480 }
481 #[test]
482 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
483 fn compute_effective_sizes_for_one_segment_memory() {
484 let mut segments = segments![((0, 0), 1), ((0, 1), 1), ((0, 2), 1)];
485 segments.compute_effective_sizes();
486 assert_eq!(Some(vec![3]), segments.segment_used_sizes);
487 }
488
489 #[test]
490 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
491 fn compute_effective_sizes_for_one_segment_memory_with_gap() {
492 let mut segments = MemorySegmentManager::new();
493 segments.add();
494 segments
495 .memory
496 .insert(
497 Relocatable::from((0, 6)),
498 &MaybeRelocatable::from(Felt252::from(1)),
499 )
500 .unwrap();
501 segments.compute_effective_sizes();
502 assert_eq!(Some(vec![7]), segments.segment_used_sizes);
503 }
504
505 #[test]
506 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
507 fn compute_effective_sizes_for_one_segment_memory_with_gaps() {
508 let mut segments = segments![((0, 3), 1), ((0, 4), 1), ((0, 7), 1), ((0, 9), 1)];
509 segments.compute_effective_sizes();
510 assert_eq!(Some(vec![10]), segments.segment_used_sizes);
511 }
512
513 #[test]
514 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
515 fn compute_effective_sizes_for_three_segment_memory() {
516 let mut segments = segments![
517 ((0, 0), 1),
518 ((0, 1), 1),
519 ((0, 2), 1),
520 ((1, 0), 1),
521 ((1, 1), 1),
522 ((1, 2), 1),
523 ((2, 0), 1),
524 ((2, 1), 1),
525 ((2, 2), 1)
526 ];
527 segments.compute_effective_sizes();
528 assert_eq!(Some(vec![3, 3, 3]), segments.segment_used_sizes);
529 }
530
531 #[test]
532 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
533 fn compute_effective_sizes_for_three_segment_memory_with_gaps() {
534 let mut segments = segments![
535 ((0, 2), 1),
536 ((0, 5), 1),
537 ((0, 7), 1),
538 ((1, 1), 1),
539 ((2, 2), 1),
540 ((2, 4), 1),
541 ((2, 7), 1)
542 ];
543 segments.compute_effective_sizes();
544 assert_eq!(Some(vec![8, 2, 8]), segments.segment_used_sizes);
545 }
546
547 #[test]
548 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
549 fn get_segment_used_size_after_computing_used() {
550 let mut segments = segments![
551 ((0, 2), 1),
552 ((0, 5), 1),
553 ((0, 7), 1),
554 ((1, 1), 1),
555 ((2, 2), 1),
556 ((2, 4), 1),
557 ((2, 7), 1)
558 ];
559 segments.compute_effective_sizes();
560 assert_eq!(Some(8), segments.get_segment_used_size(2));
561 }
562
563 #[test]
564 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
565 fn get_segment_used_size_before_computing_used() {
566 let segments = MemorySegmentManager::new();
567 assert_eq!(None, segments.get_segment_used_size(2));
568 }
569
570 #[test]
571 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
572 fn relocate_segments_one_segment() {
573 let mut segments = MemorySegmentManager::new();
574 segments.segment_used_sizes = Some(vec![3]);
575 assert_eq!(
576 segments
577 .relocate_segments()
578 .expect("Couldn't relocate after compute effective sizes"),
579 vec![1]
580 )
581 }
582
583 #[test]
584 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
585 fn relocate_segments_five_segment() {
586 let mut segments = MemorySegmentManager::new();
587 segments.segment_used_sizes = Some(vec![3, 3, 56, 78, 8]);
588 assert_eq!(
589 segments
590 .relocate_segments()
591 .expect("Couldn't relocate after compute effective sizes"),
592 vec![1, 4, 7, 63, 141]
593 )
594 }
595
596 #[test]
597 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
598 fn write_arg_relocatable() {
599 let data = vec![
600 Relocatable::from((0, 1)),
601 Relocatable::from((0, 2)),
602 Relocatable::from((0, 3)),
603 ];
604 let ptr = Relocatable::from((1, 0));
605 let mut segments = MemorySegmentManager::new();
606 for _ in 0..2 {
607 segments.add();
608 }
609
610 let exec = segments.write_arg(ptr, &data);
611
612 assert_eq!(exec, Ok(MaybeRelocatable::from((1, 3))));
613 assert_eq!(
614 segments.memory.data[1],
615 vec![
616 MemoryCell::new(MaybeRelocatable::from((0, 1))),
617 MemoryCell::new(MaybeRelocatable::from((0, 2))),
618 MemoryCell::new(MaybeRelocatable::from((0, 3))),
619 ]
620 );
621 }
622
623 #[test]
624 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
625 fn write_arg_invalid_type() {
626 let data = vec!["Invalid Type 1", "Invalid Type 2"];
627 let ptr = Relocatable::from((1, 0));
628 let mut segments = MemorySegmentManager::new();
629 for _ in 0..2 {
630 segments.add();
631 }
632
633 let exec = segments.write_arg(ptr, &data);
634
635 assert_eq!(exec, Err(MemoryError::WriteArg));
636 assert!(segments.memory.data[1].is_empty())
637 }
638
639 #[test]
640 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
641 fn segment_default() {
642 let segment_mng_new = MemorySegmentManager::new();
643 let segment_mng_def: MemorySegmentManager = Default::default();
644 assert_eq!(
645 segment_mng_new.num_segments(),
646 segment_mng_def.num_segments()
647 );
648 assert_eq!(
649 segment_mng_new.segment_used_sizes,
650 segment_mng_def.segment_used_sizes
651 );
652 }
653
654 #[test]
655 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
656 fn is_valid_memory_value_missing_effective_sizes() {
657 let segment_manager = MemorySegmentManager::new();
658
659 assert_eq!(
660 segment_manager.is_valid_memory_value(&mayberelocatable!(0)),
661 Err(MemoryError::MissingSegmentUsedSizes),
662 );
663 }
664
665 #[test]
666 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
667 fn is_valid_memory_value_temporary_segment() {
668 let mut segment_manager = MemorySegmentManager::new();
669
670 segment_manager.segment_used_sizes = Some(vec![10]);
671 assert_eq!(
672 segment_manager.is_valid_memory_value(&mayberelocatable!(-1, 0)),
673 Err(MemoryError::AddressInTemporarySegment(-1)),
674 );
675 }
676
677 #[test]
678 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
679 fn is_valid_memory_value_invalid_segment() {
680 let mut segment_manager = MemorySegmentManager::new();
681
682 segment_manager.segment_used_sizes = Some(vec![10]);
683 assert_eq!(
684 segment_manager.is_valid_memory_value(&mayberelocatable!(1, 0)),
685 Ok(false),
686 );
687 }
688
689 #[test]
690 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
691 fn is_valid_memory_value() {
692 let mut segment_manager = MemorySegmentManager::new();
693
694 segment_manager.segment_used_sizes = Some(vec![10]);
695 assert_eq!(
696 segment_manager.is_valid_memory_value(&mayberelocatable!(0, 5)),
697 Ok(true),
698 );
699 }
700
701 #[test]
702 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
703 fn is_valid_memory_value_felt() {
704 let mut segment_manager = MemorySegmentManager::new();
705
706 segment_manager.segment_used_sizes = Some(vec![10]);
707 assert_eq!(
708 segment_manager.is_valid_memory_value(&mayberelocatable!(1)),
709 Ok(true),
710 );
711 }
712
713 #[test]
714 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
715 fn get_memory_holes_missing_segment_used_sizes() {
716 let mut memory_segment_manager = MemorySegmentManager::new();
717 memory_segment_manager.memory = memory![((0, 0), 0)];
718 memory_segment_manager
719 .memory
720 .mark_as_accessed((0, 0).into());
721 assert_eq!(
722 memory_segment_manager.get_memory_holes(HashSet::new()),
723 Err(MemoryError::MissingSegmentUsedSizes),
724 );
725 }
726
727 #[test]
728 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
729 fn get_memory_holes_out_of_address_offset_bigger_than_size() {
730 let mut memory_segment_manager = MemorySegmentManager::new();
731 memory_segment_manager.segment_used_sizes = Some(vec![2]);
732 memory_segment_manager.memory = memory![((0, 0), 1), ((0, 1), 1), ((0, 2), 2)];
733 for i in 0..3 {
734 memory_segment_manager
735 .memory
736 .mark_as_accessed((0, i).into());
737 }
738 assert_eq!(
739 memory_segment_manager.get_memory_holes(HashSet::new()),
740 Err(MemoryError::SegmentHasMoreAccessedAddressesThanSize(
741 Box::new((0, 3, 2))
742 )),
743 );
744 }
745
746 #[test]
747 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
748 fn get_memory_holes_empty() {
749 let mut memory_segment_manager = MemorySegmentManager::new();
750 memory_segment_manager.segment_used_sizes = Some(Vec::new());
751 assert_eq!(
752 memory_segment_manager.get_memory_holes(HashSet::new()),
753 Ok(0),
754 );
755 }
756
757 #[test]
758 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
759 fn get_memory_holes_empty2() {
760 let mut memory_segment_manager = MemorySegmentManager::new();
761 memory_segment_manager.segment_used_sizes = Some(vec![4]);
762 assert_eq!(
763 memory_segment_manager.get_memory_holes(HashSet::new()),
764 Ok(0),
765 );
766 }
767
768 #[test]
769 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
770 fn get_memory_holes() {
771 let mut memory_segment_manager = MemorySegmentManager::new();
772 memory_segment_manager.segment_used_sizes = Some(vec![10]);
773 memory_segment_manager.memory = memory![
774 ((0, 0), 0),
775 ((0, 1), 0),
776 ((0, 2), 0),
777 ((0, 3), 0),
778 ((0, 6), 0),
779 ((0, 7), 0),
780 ((0, 8), 0),
781 ((0, 9), 0)
782 ];
783 for i in [0, 1, 2, 3, 6, 7, 8, 9] {
784 memory_segment_manager
785 .memory
786 .mark_as_accessed((0, i).into());
787 }
788 assert_eq!(
789 memory_segment_manager.get_memory_holes(HashSet::new()),
790 Ok(2),
791 );
792 }
793
794 #[test]
795 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
796 fn get_memory_holes2() {
797 let mut memory_segment_manager = MemorySegmentManager::new();
798
799 memory_segment_manager.segment_sizes = HashMap::from([(0, 15)]);
800 memory_segment_manager.memory = memory![
801 ((0, 0), 0),
802 ((0, 1), 0),
803 ((0, 2), 0),
804 ((0, 3), 0),
805 ((0, 6), 0),
806 ((0, 7), 0),
807 ((0, 8), 0),
808 ((0, 9), 0)
809 ];
810 memory_segment_manager.segment_used_sizes = Some(vec![10]);
811 for i in [0, 1, 2, 3, 6, 7, 8, 9] {
812 memory_segment_manager
813 .memory
814 .mark_as_accessed((0, i).into());
815 }
816 assert_eq!(
817 memory_segment_manager.get_memory_holes(HashSet::new()),
818 Ok(7),
819 );
820 }
821
822 #[test]
823 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
824 fn get_memory_size_missing_segment() {
825 let memory_segment_manager = MemorySegmentManager::new();
826
827 assert_eq!(memory_segment_manager.get_segment_size(0), None);
828 }
829
830 #[test]
831 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
832 fn get_memory_size_used() {
833 let mut memory_segment_manager = MemorySegmentManager::new();
834 memory_segment_manager.segment_used_sizes = Some(vec![5]);
835
836 assert_eq!(memory_segment_manager.get_segment_size(0), Some(5));
837 }
838
839 #[test]
840 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
841 fn get_memory_size() {
842 let mut memory_segment_manager = MemorySegmentManager::new();
843 memory_segment_manager.segment_sizes = HashMap::from([(0, 5)]);
844
845 assert_eq!(memory_segment_manager.get_segment_size(0), Some(5));
846 }
847
848 #[test]
849 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
850 fn get_memory_size2() {
851 let mut memory_segment_manager = MemorySegmentManager::new();
852 memory_segment_manager.segment_sizes = HashMap::from([(0, 5)]);
853 memory_segment_manager.segment_used_sizes = Some(vec![3]);
854
855 assert_eq!(memory_segment_manager.get_segment_size(0), Some(5));
856 }
857
858 #[test]
861 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
862 fn gen_arg_relocatable() {
863 let mut memory_segment_manager = MemorySegmentManager::new();
864
865 assert_matches!(
866 memory_segment_manager.gen_arg(&mayberelocatable!(0, 0)),
867 Ok(x) if x == mayberelocatable!(0, 0)
868 );
869 }
870
871 #[test]
874 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
875 fn gen_arg_bigint() {
876 let mut memory_segment_manager = MemorySegmentManager::new();
877
878 assert_matches!(
879 memory_segment_manager.gen_arg(&mayberelocatable!(1234)),
880 Ok(x) if x == mayberelocatable!(1234)
881 );
882 }
883
884 #[test]
887 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
888 fn gen_arg_vec() {
889 let mut memory_segment_manager = MemorySegmentManager::new();
890
891 assert_matches!(
892 memory_segment_manager.gen_arg(
893 &vec![
894 mayberelocatable!(0),
895 mayberelocatable!(1),
896 mayberelocatable!(2),
897 mayberelocatable!(3),
898 mayberelocatable!(0, 0),
899 mayberelocatable!(0, 1),
900 mayberelocatable!(0, 2),
901 mayberelocatable!(0, 3),
902 ],
903 ),
904 Ok(x) if x == mayberelocatable!(0, 0)
905 );
906 }
907
908 #[test]
911 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
912 fn gen_arg_vec_mayberelocatables() {
913 let mut memory_segment_manager = MemorySegmentManager::new();
914
915 assert_matches!(
916 memory_segment_manager.gen_arg(
917 &vec![
918 MaybeRelocatable::from((0, 0)),
919 MaybeRelocatable::from((0, 1)),
920 MaybeRelocatable::from((0, 2)),
921 MaybeRelocatable::from((0, 3)),
922 ],
923 ),
924 Ok(x) if x == mayberelocatable!(0, 0)
925 );
926 assert_eq!(
927 memory_segment_manager.memory.data[0],
928 vec![
929 MemoryCell::new(MaybeRelocatable::from((0, 0))),
930 MemoryCell::new(MaybeRelocatable::from((0, 1))),
931 MemoryCell::new(MaybeRelocatable::from((0, 2))),
932 MemoryCell::new(MaybeRelocatable::from((0, 3))),
933 ],
934 );
935 }
936
937 #[test]
940 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
941 fn gen_arg_vec_relocatables() {
942 let mut memory_segment_manager = MemorySegmentManager::new();
943
944 assert_matches!(
945 memory_segment_manager.gen_arg(
946 &vec![
947 Relocatable::from((0, 0)),
948 Relocatable::from((0, 1)),
949 Relocatable::from((0, 2)),
950 Relocatable::from((0, 3)),
951 ],
952 ),
953 Ok(x) if x == mayberelocatable!(0, 0)
954 );
955 assert_eq!(
956 memory_segment_manager.memory.data[0],
957 vec![
958 MemoryCell::new(MaybeRelocatable::from((0, 0))),
959 MemoryCell::new(MaybeRelocatable::from((0, 1))),
960 MemoryCell::new(MaybeRelocatable::from((0, 2))),
961 MemoryCell::new(MaybeRelocatable::from((0, 3))),
962 ],
963 );
964 }
965
966 #[test]
969 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
970 fn gen_arg_invalid_type() {
971 let mut memory_segment_manager = MemorySegmentManager::new();
972
973 assert_matches!(
974 memory_segment_manager.gen_arg(&""),
975 Err(MemoryError::GenArgInvalidType)
976 );
977 }
978
979 #[test]
980 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
981 fn finalize_no_size_nor_memory() {
982 let mut segments = MemorySegmentManager::new();
983 segments.finalize(None, 0, None);
984 assert!(segments.memory.data.is_empty());
985 assert!(segments.memory.temp_data.is_empty());
986 assert_eq!(segments.public_memory_offsets, HashMap::from([(0, vec![])]));
987 assert_eq!(segments.num_segments(), 0);
988 assert_eq!(segments.num_temp_segments(), 0);
989 }
990
991 #[test]
992 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
993 fn finalize_no_memory() {
994 let mut segments = MemorySegmentManager::new();
995 segments.finalize(Some(42), 0, None);
996 assert_eq!(segments.public_memory_offsets, HashMap::from([(0, vec![])]));
997 assert_eq!(segments.segment_sizes, HashMap::from([(0, 42)]));
998 }
999
1000 #[test]
1001 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1002 fn finalize_no_size() {
1003 let mut segments = MemorySegmentManager::new();
1004 segments.finalize(None, 0, Some(&vec![(1_usize, 2_usize)]));
1005 assert_eq!(
1006 segments.public_memory_offsets,
1007 HashMap::from([(0_usize, vec![(1_usize, 2_usize)])])
1008 );
1009 assert!(segments.segment_sizes.is_empty());
1010 }
1011
1012 #[test]
1013 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1014 fn finalize_all_args() {
1015 let mut segments = MemorySegmentManager::new();
1016 segments.finalize(Some(42), 0, Some(&vec![(1_usize, 2_usize)]));
1017 assert_eq!(
1018 segments.public_memory_offsets,
1019 HashMap::from([(0_usize, vec![(1_usize, 2_usize)])])
1020 );
1021 assert_eq!(segments.segment_sizes, HashMap::from([(0, 42)]));
1022 }
1023
1024 #[test]
1025 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1026 fn gen_cairo_arg_single() {
1027 let mut memory_segment_manager = MemorySegmentManager::new();
1028
1029 assert_matches!(
1030 memory_segment_manager.gen_cairo_arg(&mayberelocatable!(1234).into()),
1031 Ok(x) if x == mayberelocatable!(1234)
1032 );
1033 }
1034
1035 #[test]
1036 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1037 fn gen_cairo_arg_array() {
1038 let mut memory_segment_manager = MemorySegmentManager::new();
1039
1040 assert_matches!(
1041 memory_segment_manager.gen_cairo_arg(
1042 &vec![
1043 mayberelocatable!(0),
1044 mayberelocatable!(1),
1045 mayberelocatable!(2),
1046 mayberelocatable!(3),
1047 mayberelocatable!(0, 0),
1048 mayberelocatable!(0, 1),
1049 mayberelocatable!(0, 2),
1050 mayberelocatable!(0, 3),
1051 ]
1052 .into(),
1053 ),
1054 Ok(x) if x == mayberelocatable!(0, 0)
1055 );
1056 }
1057
1058 #[test]
1059 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1060 fn gen_cairo_arg_composed() {
1061 let mut memory_segment_manager = MemorySegmentManager::new();
1062 let cairo_args = CairoArg::Composed(vec![
1063 CairoArg::Array(vec![
1064 mayberelocatable!(0),
1065 mayberelocatable!(1),
1066 mayberelocatable!(2),
1067 ]),
1068 CairoArg::Single(mayberelocatable!(1234)),
1069 CairoArg::Single(mayberelocatable!(5678)),
1070 CairoArg::Array(vec![
1071 mayberelocatable!(3),
1072 mayberelocatable!(4),
1073 mayberelocatable!(5),
1074 ]),
1075 ]);
1076
1077 assert_matches!(
1078 memory_segment_manager.gen_cairo_arg(&cairo_args),
1079 Ok(x) if x == mayberelocatable!(2, 0)
1080 );
1081 }
1082
1083 #[test]
1084 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1085 fn test_add_zero_segment() {
1086 let mut memory_segment_manager = MemorySegmentManager::new();
1088 memory_segment_manager.add();
1089 memory_segment_manager.add();
1090
1091 memory_segment_manager.add_zero_segment(3);
1093 assert_eq!(memory_segment_manager.zero_segment_index, 2);
1094 assert_eq!(memory_segment_manager.zero_segment_size, 3);
1095 assert_eq!(
1096 &memory_segment_manager.memory.data[2],
1097 &Vec::from([
1098 MemoryCell::new(MaybeRelocatable::from(0)),
1099 MemoryCell::new(MaybeRelocatable::from(0)),
1100 MemoryCell::new(MaybeRelocatable::from(0))
1101 ])
1102 );
1103
1104 memory_segment_manager.add_zero_segment(5);
1106 assert_eq!(memory_segment_manager.zero_segment_index, 2);
1107 assert_eq!(memory_segment_manager.zero_segment_size, 5);
1108
1109 assert_eq!(
1110 &memory_segment_manager.memory.data[2],
1111 &Vec::from([
1112 MemoryCell::new(MaybeRelocatable::from(0)),
1113 MemoryCell::new(MaybeRelocatable::from(0)),
1114 MemoryCell::new(MaybeRelocatable::from(0)),
1115 MemoryCell::new(MaybeRelocatable::from(0)),
1116 MemoryCell::new(MaybeRelocatable::from(0))
1117 ])
1118 );
1119 }
1120}