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(crate) 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 get_memory_holes(
207 &self,
208 builtin_segment_indexes: HashSet<usize>,
209 ) -> Result<usize, MemoryError> {
210 let data = &self.memory.data;
211 let mut memory_holes = 0;
212 for i in 0..data.len() {
213 if builtin_segment_indexes.contains(&i) {
216 continue;
217 }
218 let accessed_amount =
219 if self.has_zero_segment() && i == self.zero_segment_index {
221 self.zero_segment_size
222 } else {
223 match self.memory.get_amount_of_accessed_addresses_for_segment(i) {
224 Some(accessed_amount) if accessed_amount > 0 => accessed_amount,
225 _ => continue,
226 }
227 };
228 let segment_size = self
229 .get_segment_size(i)
230 .ok_or(MemoryError::MissingSegmentUsedSizes)?;
231 if accessed_amount > segment_size {
232 return Err(MemoryError::SegmentHasMoreAccessedAddressesThanSize(
233 Box::new((i, accessed_amount, segment_size)),
234 ));
235 }
236 memory_holes += segment_size - accessed_amount;
237 }
238 Ok(memory_holes)
239 }
240
241 pub fn get_public_memory_addresses(
244 &self,
245 segment_offsets: &[usize],
246 ) -> Result<Vec<(usize, usize)>, MemoryError> {
247 let mut addresses = Vec::with_capacity(self.num_segments());
248 let empty_vec = vec![];
249 for segment_index in 0..self.num_segments() {
250 let offsets = &self
251 .public_memory_offsets
252 .get(&segment_index)
253 .unwrap_or(&empty_vec);
254 let segment_start = segment_offsets
255 .get(segment_index)
256 .ok_or(MemoryError::MalformedPublicMemory)?;
257 for (offset, page_id) in offsets.iter() {
258 addresses.push((segment_start + offset, *page_id));
259 }
260 }
261 Ok(addresses)
262 }
263
264 pub fn finalize(
269 &mut self,
270 size: Option<usize>,
271 segment_index: usize,
272 public_memory: Option<&Vec<(usize, usize)>>,
273 ) {
274 if let Some(size) = size {
275 self.segment_sizes.insert(segment_index, size);
276 }
277 self.public_memory_offsets
278 .insert(segment_index, public_memory.cloned().unwrap_or_default());
279 }
280
281 pub fn has_zero_segment(&self) -> bool {
282 !self.zero_segment_index.is_zero()
283 }
284
285 pub(crate) fn add_zero_segment(&mut self, size: usize) -> usize {
289 if !self.has_zero_segment() {
290 self.zero_segment_index = self.add().segment_index as usize;
291 }
292
293 for _ in 0..(size.saturating_sub(self.zero_segment_size)) {
295 self.memory.data[self.zero_segment_index].push(MemoryCell::new(Felt252::ZERO.into()))
298 }
299 self.zero_segment_size = max(self.zero_segment_size, size);
300 self.zero_segment_index
301 }
302
303 pub(crate) fn finalize_zero_segment(&mut self) {
305 if self.has_zero_segment() {
306 self.finalize(Some(self.zero_segment_size), self.zero_segment_index, None);
307 self.zero_segment_index = 0;
308 self.zero_segment_size = 0;
309 }
310 }
311
312 pub(crate) fn load_pie_memory(
313 &mut self,
314 pie_memory: &CairoPieMemory,
315 n_extra_segments: usize,
316 ) -> Result<(), MemoryError> {
317 for _ in 0..n_extra_segments {
319 self.add();
320 }
321 for ((si, so), val) in pie_memory.0.iter() {
323 self.memory.insert((*si as isize, *so).into(), val)?;
324 }
325 Ok(())
326 }
327}
328
329impl Default for MemorySegmentManager {
330 fn default() -> Self {
331 Self::new()
332 }
333}
334
335impl fmt::Display for MemorySegmentManager {
336 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
337 writeln!(f, "Memory:\n{}", self.memory)?;
338 if let Some(used_sizes) = &self.segment_used_sizes {
339 writeln!(f, "Segment Info:")?;
340 for (index, used_size) in used_sizes.iter().enumerate() {
341 writeln!(
342 f,
343 "Segment Number: {}, Used Size: {}, Size {}",
344 index,
345 used_size,
346 self.segment_sizes
347 .get(&index)
348 .map(|n| n.to_string())
349 .unwrap_or(String::from("None"))
350 )?;
351 }
352 }
353 Ok(())
354 }
355}
356
357#[cfg(test)]
358mod tests {
359 use super::*;
360 use crate::Felt252;
361 use crate::{relocatable, utils::test_utils::*, vm::vm_memory::memory::MemoryCell};
362 use assert_matches::assert_matches;
363
364 #[cfg(target_arch = "wasm32")]
365 use wasm_bindgen_test::*;
366
367 #[test]
368 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
369 fn add_segment_no_size() {
370 let mut segments = MemorySegmentManager::new();
371 let base = segments.add();
372 assert_eq!(base, relocatable!(0, 0));
373 assert_eq!(segments.num_segments(), 1);
374 }
375
376 #[test]
377 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
378 fn add_segment_no_size_test_two_segments() {
379 let mut segments = MemorySegmentManager::new();
380 let mut _base = segments.add();
381 _base = segments.add();
382 assert_eq!(
383 _base,
384 Relocatable {
385 segment_index: 1,
386 offset: 0
387 }
388 );
389 assert_eq!(segments.num_segments(), 2);
390 }
391
392 #[test]
393 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
394 fn add_one_temporary_segment() {
395 let mut segments = MemorySegmentManager::new();
396 let base = segments.add_temporary_segment();
397 assert_eq!(base, relocatable!(-1, 0));
398 assert_eq!(segments.num_temp_segments(), 1);
399 }
400
401 #[test]
402 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
403 fn add_two_temporary_segments() {
404 let mut segments = MemorySegmentManager::new();
405 segments.add_temporary_segment();
406 let base = segments.add_temporary_segment();
407 assert_eq!(
408 base,
409 Relocatable {
410 segment_index: -2,
411 offset: 0
412 }
413 );
414 assert_eq!(segments.num_temp_segments(), 2);
415 }
416
417 #[test]
418 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
419 fn load_data_empty() {
420 let data = Vec::new();
421 let ptr = Relocatable::from((0, 3));
422 let mut segments = MemorySegmentManager::new();
423 let current_ptr = segments.load_data(ptr, &data).unwrap();
424 assert_eq!(current_ptr, Relocatable::from((0, 3)));
425 }
426
427 #[test]
428 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
429 fn load_data_one_element() {
430 let data = vec![MaybeRelocatable::from(Felt252::from(4))];
431 let ptr = Relocatable::from((0, 0));
432 let mut segments = MemorySegmentManager::new();
433 segments.add();
434 let current_ptr = segments.load_data(ptr, &data).unwrap();
435 assert_eq!(current_ptr, Relocatable::from((0, 1)));
436 assert_eq!(
437 segments.memory.get(&ptr).unwrap().as_ref(),
438 &MaybeRelocatable::from(Felt252::from(4))
439 );
440 }
441
442 #[test]
443 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
444 fn load_data_three_elements() {
445 let data = vec![
446 MaybeRelocatable::from(Felt252::from(4)),
447 MaybeRelocatable::from(Felt252::from(5)),
448 MaybeRelocatable::from(Felt252::from(6)),
449 ];
450 let ptr = Relocatable::from((0, 0));
451 let mut segments = MemorySegmentManager::new();
452 segments.add();
453 let current_ptr = segments.load_data(ptr, &data).unwrap();
454 assert_eq!(current_ptr, Relocatable::from((0, 3)));
455
456 assert_eq!(
457 segments.memory.get(&ptr).unwrap().as_ref(),
458 &MaybeRelocatable::from(Felt252::from(4))
459 );
460 assert_eq!(
461 segments
462 .memory
463 .get(&MaybeRelocatable::from((0, 1)))
464 .unwrap()
465 .as_ref(),
466 &MaybeRelocatable::from(Felt252::from(5))
467 );
468 assert_eq!(
469 segments
470 .memory
471 .get(&MaybeRelocatable::from((0, 2)))
472 .unwrap()
473 .as_ref(),
474 &MaybeRelocatable::from(Felt252::from(6))
475 );
476 }
477 #[test]
478 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
479 fn compute_effective_sizes_for_one_segment_memory() {
480 let mut segments = segments![((0, 0), 1), ((0, 1), 1), ((0, 2), 1)];
481 segments.compute_effective_sizes();
482 assert_eq!(Some(vec![3]), segments.segment_used_sizes);
483 }
484
485 #[test]
486 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
487 fn compute_effective_sizes_for_one_segment_memory_with_gap() {
488 let mut segments = MemorySegmentManager::new();
489 segments.add();
490 segments
491 .memory
492 .insert(
493 Relocatable::from((0, 6)),
494 &MaybeRelocatable::from(Felt252::from(1)),
495 )
496 .unwrap();
497 segments.compute_effective_sizes();
498 assert_eq!(Some(vec![7]), segments.segment_used_sizes);
499 }
500
501 #[test]
502 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
503 fn compute_effective_sizes_for_one_segment_memory_with_gaps() {
504 let mut segments = segments![((0, 3), 1), ((0, 4), 1), ((0, 7), 1), ((0, 9), 1)];
505 segments.compute_effective_sizes();
506 assert_eq!(Some(vec![10]), segments.segment_used_sizes);
507 }
508
509 #[test]
510 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
511 fn compute_effective_sizes_for_three_segment_memory() {
512 let mut segments = segments![
513 ((0, 0), 1),
514 ((0, 1), 1),
515 ((0, 2), 1),
516 ((1, 0), 1),
517 ((1, 1), 1),
518 ((1, 2), 1),
519 ((2, 0), 1),
520 ((2, 1), 1),
521 ((2, 2), 1)
522 ];
523 segments.compute_effective_sizes();
524 assert_eq!(Some(vec![3, 3, 3]), segments.segment_used_sizes);
525 }
526
527 #[test]
528 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
529 fn compute_effective_sizes_for_three_segment_memory_with_gaps() {
530 let mut segments = segments![
531 ((0, 2), 1),
532 ((0, 5), 1),
533 ((0, 7), 1),
534 ((1, 1), 1),
535 ((2, 2), 1),
536 ((2, 4), 1),
537 ((2, 7), 1)
538 ];
539 segments.compute_effective_sizes();
540 assert_eq!(Some(vec![8, 2, 8]), segments.segment_used_sizes);
541 }
542
543 #[test]
544 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
545 fn get_segment_used_size_after_computing_used() {
546 let mut segments = segments![
547 ((0, 2), 1),
548 ((0, 5), 1),
549 ((0, 7), 1),
550 ((1, 1), 1),
551 ((2, 2), 1),
552 ((2, 4), 1),
553 ((2, 7), 1)
554 ];
555 segments.compute_effective_sizes();
556 assert_eq!(Some(8), segments.get_segment_used_size(2));
557 }
558
559 #[test]
560 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
561 fn get_segment_used_size_before_computing_used() {
562 let segments = MemorySegmentManager::new();
563 assert_eq!(None, segments.get_segment_used_size(2));
564 }
565
566 #[test]
567 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
568 fn relocate_segments_one_segment() {
569 let mut segments = MemorySegmentManager::new();
570 segments.segment_used_sizes = Some(vec![3]);
571 assert_eq!(
572 segments
573 .relocate_segments()
574 .expect("Couldn't relocate after compute effective sizes"),
575 vec![1]
576 )
577 }
578
579 #[test]
580 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
581 fn relocate_segments_five_segment() {
582 let mut segments = MemorySegmentManager::new();
583 segments.segment_used_sizes = Some(vec![3, 3, 56, 78, 8]);
584 assert_eq!(
585 segments
586 .relocate_segments()
587 .expect("Couldn't relocate after compute effective sizes"),
588 vec![1, 4, 7, 63, 141]
589 )
590 }
591
592 #[test]
593 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
594 fn write_arg_relocatable() {
595 let data = vec![
596 Relocatable::from((0, 1)),
597 Relocatable::from((0, 2)),
598 Relocatable::from((0, 3)),
599 ];
600 let ptr = Relocatable::from((1, 0));
601 let mut segments = MemorySegmentManager::new();
602 for _ in 0..2 {
603 segments.add();
604 }
605
606 let exec = segments.write_arg(ptr, &data);
607
608 assert_eq!(exec, Ok(MaybeRelocatable::from((1, 3))));
609 assert_eq!(
610 segments.memory.data[1],
611 vec![
612 MemoryCell::new(MaybeRelocatable::from((0, 1))),
613 MemoryCell::new(MaybeRelocatable::from((0, 2))),
614 MemoryCell::new(MaybeRelocatable::from((0, 3))),
615 ]
616 );
617 }
618
619 #[test]
620 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
621 fn segment_default() {
622 let segment_mng_new = MemorySegmentManager::new();
623 let segment_mng_def: MemorySegmentManager = Default::default();
624 assert_eq!(
625 segment_mng_new.num_segments(),
626 segment_mng_def.num_segments()
627 );
628 assert_eq!(
629 segment_mng_new.segment_used_sizes,
630 segment_mng_def.segment_used_sizes
631 );
632 }
633
634 #[test]
635 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
636 fn is_valid_memory_value_missing_effective_sizes() {
637 let segment_manager = MemorySegmentManager::new();
638
639 assert_eq!(
640 segment_manager.is_valid_memory_value(&mayberelocatable!(0)),
641 Err(MemoryError::MissingSegmentUsedSizes),
642 );
643 }
644
645 #[test]
646 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
647 fn is_valid_memory_value_temporary_segment() {
648 let mut segment_manager = MemorySegmentManager::new();
649
650 segment_manager.segment_used_sizes = Some(vec![10]);
651 assert_eq!(
652 segment_manager.is_valid_memory_value(&mayberelocatable!(-1, 0)),
653 Err(MemoryError::AddressInTemporarySegment(-1)),
654 );
655 }
656
657 #[test]
658 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
659 fn is_valid_memory_value_invalid_segment() {
660 let mut segment_manager = MemorySegmentManager::new();
661
662 segment_manager.segment_used_sizes = Some(vec![10]);
663 assert_eq!(
664 segment_manager.is_valid_memory_value(&mayberelocatable!(1, 0)),
665 Ok(false),
666 );
667 }
668
669 #[test]
670 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
671 fn is_valid_memory_value() {
672 let mut segment_manager = MemorySegmentManager::new();
673
674 segment_manager.segment_used_sizes = Some(vec![10]);
675 assert_eq!(
676 segment_manager.is_valid_memory_value(&mayberelocatable!(0, 5)),
677 Ok(true),
678 );
679 }
680
681 #[test]
682 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
683 fn get_memory_holes_missing_segment_used_sizes() {
684 let mut memory_segment_manager = MemorySegmentManager::new();
685 memory_segment_manager.memory = memory![((0, 0), 0)];
686 memory_segment_manager
687 .memory
688 .mark_as_accessed((0, 0).into());
689 assert_eq!(
690 memory_segment_manager.get_memory_holes(HashSet::new()),
691 Err(MemoryError::MissingSegmentUsedSizes),
692 );
693 }
694
695 #[test]
696 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
697 fn get_memory_holes_out_of_address_offset_bigger_than_size() {
698 let mut memory_segment_manager = MemorySegmentManager::new();
699 memory_segment_manager.segment_used_sizes = Some(vec![2]);
700 memory_segment_manager.memory = memory![((0, 0), 1), ((0, 1), 1), ((0, 2), 2)];
701 for i in 0..3 {
702 memory_segment_manager
703 .memory
704 .mark_as_accessed((0, i).into());
705 }
706 assert_eq!(
707 memory_segment_manager.get_memory_holes(HashSet::new()),
708 Err(MemoryError::SegmentHasMoreAccessedAddressesThanSize(
709 Box::new((0, 3, 2))
710 )),
711 );
712 }
713
714 #[test]
715 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
716 fn get_memory_holes_empty() {
717 let mut memory_segment_manager = MemorySegmentManager::new();
718 memory_segment_manager.segment_used_sizes = Some(Vec::new());
719 assert_eq!(
720 memory_segment_manager.get_memory_holes(HashSet::new()),
721 Ok(0),
722 );
723 }
724
725 #[test]
726 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_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 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
738 fn get_memory_holes() {
739 let mut memory_segment_manager = MemorySegmentManager::new();
740 memory_segment_manager.segment_used_sizes = Some(vec![10]);
741 memory_segment_manager.memory = memory![
742 ((0, 0), 0),
743 ((0, 1), 0),
744 ((0, 2), 0),
745 ((0, 3), 0),
746 ((0, 6), 0),
747 ((0, 7), 0),
748 ((0, 8), 0),
749 ((0, 9), 0)
750 ];
751 for i in [0, 1, 2, 3, 6, 7, 8, 9] {
752 memory_segment_manager
753 .memory
754 .mark_as_accessed((0, i).into());
755 }
756 assert_eq!(
757 memory_segment_manager.get_memory_holes(HashSet::new()),
758 Ok(2),
759 );
760 }
761
762 #[test]
763 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
764 fn get_memory_holes2() {
765 let mut memory_segment_manager = MemorySegmentManager::new();
766
767 memory_segment_manager.segment_sizes = HashMap::from([(0, 15)]);
768 memory_segment_manager.memory = memory![
769 ((0, 0), 0),
770 ((0, 1), 0),
771 ((0, 2), 0),
772 ((0, 3), 0),
773 ((0, 6), 0),
774 ((0, 7), 0),
775 ((0, 8), 0),
776 ((0, 9), 0)
777 ];
778 memory_segment_manager.segment_used_sizes = Some(vec![10]);
779 for i in [0, 1, 2, 3, 6, 7, 8, 9] {
780 memory_segment_manager
781 .memory
782 .mark_as_accessed((0, i).into());
783 }
784 assert_eq!(
785 memory_segment_manager.get_memory_holes(HashSet::new()),
786 Ok(7),
787 );
788 }
789
790 #[test]
791 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
792 fn get_memory_size_missing_segment() {
793 let memory_segment_manager = MemorySegmentManager::new();
794
795 assert_eq!(memory_segment_manager.get_segment_size(0), None);
796 }
797
798 #[test]
799 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
800 fn get_memory_size_used() {
801 let mut memory_segment_manager = MemorySegmentManager::new();
802 memory_segment_manager.segment_used_sizes = Some(vec![5]);
803
804 assert_eq!(memory_segment_manager.get_segment_size(0), Some(5));
805 }
806
807 #[test]
808 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
809 fn get_memory_size() {
810 let mut memory_segment_manager = MemorySegmentManager::new();
811 memory_segment_manager.segment_sizes = HashMap::from([(0, 5)]);
812
813 assert_eq!(memory_segment_manager.get_segment_size(0), Some(5));
814 }
815
816 #[test]
817 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
818 fn get_memory_size2() {
819 let mut memory_segment_manager = MemorySegmentManager::new();
820 memory_segment_manager.segment_sizes = HashMap::from([(0, 5)]);
821 memory_segment_manager.segment_used_sizes = Some(vec![3]);
822
823 assert_eq!(memory_segment_manager.get_segment_size(0), Some(5));
824 }
825
826 #[test]
829 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
830 fn gen_arg_relocatable() {
831 let mut memory_segment_manager = MemorySegmentManager::new();
832
833 assert_matches!(
834 memory_segment_manager.gen_arg(&mayberelocatable!(0, 0)),
835 Ok(x) if x == mayberelocatable!(0, 0)
836 );
837 }
838
839 #[test]
842 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
843 fn gen_arg_bigint() {
844 let mut memory_segment_manager = MemorySegmentManager::new();
845
846 assert_matches!(
847 memory_segment_manager.gen_arg(&mayberelocatable!(1234)),
848 Ok(x) if x == mayberelocatable!(1234)
849 );
850 }
851
852 #[test]
855 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
856 fn gen_arg_vec() {
857 let mut memory_segment_manager = MemorySegmentManager::new();
858
859 assert_matches!(
860 memory_segment_manager.gen_arg(
861 &vec![
862 mayberelocatable!(0),
863 mayberelocatable!(1),
864 mayberelocatable!(2),
865 mayberelocatable!(3),
866 mayberelocatable!(0, 0),
867 mayberelocatable!(0, 1),
868 mayberelocatable!(0, 2),
869 mayberelocatable!(0, 3),
870 ],
871 ),
872 Ok(x) if x == mayberelocatable!(0, 0)
873 );
874 }
875
876 #[test]
879 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
880 fn gen_arg_vec_relocatable() {
881 let mut memory_segment_manager = MemorySegmentManager::new();
882
883 assert_matches!(
884 memory_segment_manager.gen_arg(
885 &vec![
886 MaybeRelocatable::from((0, 0)),
887 MaybeRelocatable::from((0, 1)),
888 MaybeRelocatable::from((0, 2)),
889 MaybeRelocatable::from((0, 3)),
890 ],
891 ),
892 Ok(x) if x == mayberelocatable!(0, 0)
893 );
894 }
895
896 #[test]
899 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
900 fn gen_arg_invalid_type() {
901 let mut memory_segment_manager = MemorySegmentManager::new();
902
903 assert_matches!(
904 memory_segment_manager.gen_arg(&""),
905 Err(MemoryError::GenArgInvalidType)
906 );
907 }
908
909 #[test]
910 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
911 fn finalize_no_size_nor_memory() {
912 let mut segments = MemorySegmentManager::new();
913 segments.finalize(None, 0, None);
914 assert!(segments.memory.data.is_empty());
915 assert!(segments.memory.temp_data.is_empty());
916 assert_eq!(segments.public_memory_offsets, HashMap::from([(0, vec![])]));
917 assert_eq!(segments.num_segments(), 0);
918 assert_eq!(segments.num_temp_segments(), 0);
919 }
920
921 #[test]
922 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
923 fn finalize_no_memory() {
924 let mut segments = MemorySegmentManager::new();
925 segments.finalize(Some(42), 0, None);
926 assert_eq!(segments.public_memory_offsets, HashMap::from([(0, vec![])]));
927 assert_eq!(segments.segment_sizes, HashMap::from([(0, 42)]));
928 }
929
930 #[test]
931 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
932 fn finalize_no_size() {
933 let mut segments = MemorySegmentManager::new();
934 segments.finalize(None, 0, Some(&vec![(1_usize, 2_usize)]));
935 assert_eq!(
936 segments.public_memory_offsets,
937 HashMap::from([(0_usize, vec![(1_usize, 2_usize)])])
938 );
939 assert!(segments.segment_sizes.is_empty());
940 }
941
942 #[test]
943 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
944 fn finalize_all_args() {
945 let mut segments = MemorySegmentManager::new();
946 segments.finalize(Some(42), 0, Some(&vec![(1_usize, 2_usize)]));
947 assert_eq!(
948 segments.public_memory_offsets,
949 HashMap::from([(0_usize, vec![(1_usize, 2_usize)])])
950 );
951 assert_eq!(segments.segment_sizes, HashMap::from([(0, 42)]));
952 }
953
954 #[test]
955 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
956 fn gen_cairo_arg_single() {
957 let mut memory_segment_manager = MemorySegmentManager::new();
958
959 assert_matches!(
960 memory_segment_manager.gen_cairo_arg(&mayberelocatable!(1234).into()),
961 Ok(x) if x == mayberelocatable!(1234)
962 );
963 }
964
965 #[test]
966 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
967 fn gen_cairo_arg_array() {
968 let mut memory_segment_manager = MemorySegmentManager::new();
969
970 assert_matches!(
971 memory_segment_manager.gen_cairo_arg(
972 &vec![
973 mayberelocatable!(0),
974 mayberelocatable!(1),
975 mayberelocatable!(2),
976 mayberelocatable!(3),
977 mayberelocatable!(0, 0),
978 mayberelocatable!(0, 1),
979 mayberelocatable!(0, 2),
980 mayberelocatable!(0, 3),
981 ]
982 .into(),
983 ),
984 Ok(x) if x == mayberelocatable!(0, 0)
985 );
986 }
987
988 #[test]
989 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
990 fn gen_cairo_arg_composed() {
991 let mut memory_segment_manager = MemorySegmentManager::new();
992 let cairo_args = CairoArg::Composed(vec![
993 CairoArg::Array(vec![
994 mayberelocatable!(0),
995 mayberelocatable!(1),
996 mayberelocatable!(2),
997 ]),
998 CairoArg::Single(mayberelocatable!(1234)),
999 CairoArg::Single(mayberelocatable!(5678)),
1000 CairoArg::Array(vec![
1001 mayberelocatable!(3),
1002 mayberelocatable!(4),
1003 mayberelocatable!(5),
1004 ]),
1005 ]);
1006
1007 assert_matches!(
1008 memory_segment_manager.gen_cairo_arg(&cairo_args),
1009 Ok(x) if x == mayberelocatable!(2, 0)
1010 );
1011 }
1012
1013 #[test]
1014 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1015 fn test_add_zero_segment() {
1016 let mut memory_segment_manager = MemorySegmentManager::new();
1018 memory_segment_manager.add();
1019 memory_segment_manager.add();
1020
1021 memory_segment_manager.add_zero_segment(3);
1023 assert_eq!(memory_segment_manager.zero_segment_index, 2);
1024 assert_eq!(memory_segment_manager.zero_segment_size, 3);
1025 assert_eq!(
1026 &memory_segment_manager.memory.data[2],
1027 &Vec::from([
1028 MemoryCell::new(MaybeRelocatable::from(0)),
1029 MemoryCell::new(MaybeRelocatable::from(0)),
1030 MemoryCell::new(MaybeRelocatable::from(0))
1031 ])
1032 );
1033
1034 memory_segment_manager.add_zero_segment(5);
1036 assert_eq!(memory_segment_manager.zero_segment_index, 2);
1037 assert_eq!(memory_segment_manager.zero_segment_size, 5);
1038
1039 assert_eq!(
1040 &memory_segment_manager.memory.data[2],
1041 &Vec::from([
1042 MemoryCell::new(MaybeRelocatable::from(0)),
1043 MemoryCell::new(MaybeRelocatable::from(0)),
1044 MemoryCell::new(MaybeRelocatable::from(0)),
1045 MemoryCell::new(MaybeRelocatable::from(0)),
1046 MemoryCell::new(MaybeRelocatable::from(0))
1047 ])
1048 );
1049 }
1050}