1use std::{
5 fmt::{Display, Formatter, Result},
6 ops::{Index, IndexMut},
7};
8
9use crate::{helper::*, word::CairoWord};
10use ark_ff::Field;
11use core::iter::repeat;
12
13pub struct CairoMemory<F> {
15 codelen: usize,
17 data: Vec<Option<CairoWord<F>>>,
19}
20
21impl<F: Field> Index<F> for CairoMemory<F> {
22 type Output = Option<CairoWord<F>>;
23 fn index(&self, idx: F) -> &Self::Output {
24 let addr: u64 = idx.to_u64();
27 &self.data[addr as usize]
28 }
29}
30
31impl<F: Field> IndexMut<F> for CairoMemory<F> {
32 fn index_mut(&mut self, idx: F) -> &mut Self::Output {
33 let addr: u64 = idx.to_u64();
34 self.resize(addr); &mut self.data[addr as usize]
36 }
37}
38
39impl<F: Field> Display for CairoMemory<F> {
40 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
41 for i in 1..self.len() {
42 if let Some(elem) = self[F::from(i)] {
44 writeln!(f, "{0:>6}: 0x{1:}", i, elem.word().to_hex_be())
45 .map_err(|_| core::fmt::Error)?;
46 } else {
47 writeln!(f, "{i:>6}: None").map_err(|_| core::fmt::Error)?;
48 }
49 }
50 Ok(())
51 }
52}
53
54impl<F: Field> CairoMemory<F> {
55 pub fn new(input: Vec<F>) -> CairoMemory<F> {
57 let mut aux = vec![F::zero()];
60 aux.extend(input);
61 CairoMemory {
62 codelen: aux.len() - 1,
63 data: aux.into_iter().map(|i| Some(CairoWord::new(i))).collect(),
64 }
65 }
66
67 pub fn get_codelen(&self) -> usize {
69 self.codelen
70 }
71
72 pub fn len(&self) -> u64 {
74 self.data.len() as u64
75 }
76
77 pub fn is_empty(&self) -> bool {
79 self.data.len() < 2
80 }
81
82 fn resize(&mut self, addr: u64) {
84 if let Some(additional) = addr.checked_sub(self.len() - 1) {
88 self.data.extend(repeat(None).take(additional as usize));
89 }
90 }
91
92 pub fn write(&mut self, addr: F, elem: F) {
94 self[addr] = Some(CairoWord::new(elem));
95 }
96
97 pub fn read(&mut self, addr: F) -> Option<F> {
99 self.resize(addr.to_u64()); self[addr].map(|x| x.word())
101 }
102}