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