essential_constraint_vm/
memory.rs

1use essential_types::Word;
2
3use crate::{error::TemporaryError, OpResult};
4
5#[cfg(test)]
6mod tests;
7
8#[derive(Default, Debug, PartialEq)]
9/// Memory for temporary storage of words.
10pub struct Memory(Vec<Word>);
11
12impl Memory {
13    /// The maximum number of words that can be stored in memory.
14    pub const SIZE_LIMIT: usize = 1024 * 10;
15
16    /// Create a new temporary memory instance.
17    pub fn new() -> Self {
18        Self::default()
19    }
20
21    /// Allocate more memory to the end of this memory.
22    pub fn alloc(&mut self, size: Word) -> OpResult<()> {
23        let size = usize::try_from(size).map_err(|_| TemporaryError::Overflow)?;
24        let new_size = self
25            .0
26            .len()
27            .checked_add(size)
28            .ok_or(TemporaryError::Overflow)?;
29        if new_size > Self::SIZE_LIMIT {
30            return Err(TemporaryError::Overflow.into());
31        }
32        self.0.resize(new_size, 0);
33        Ok(())
34    }
35
36    /// Store a word at the given address.
37    pub fn store(&mut self, address: Word, value: Word) -> OpResult<()> {
38        let index = usize::try_from(address).map_err(|_| TemporaryError::IndexOutOfBounds)?;
39        *self
40            .0
41            .get_mut(index)
42            .ok_or(TemporaryError::IndexOutOfBounds)? = value;
43        Ok(())
44    }
45
46    /// Load a word from the given address.
47    pub fn load(&mut self, address: Word) -> OpResult<Word> {
48        let index = usize::try_from(address).map_err(|_| TemporaryError::IndexOutOfBounds)?;
49        Ok(*self.0.get(index).ok_or(TemporaryError::IndexOutOfBounds)?)
50    }
51
52    /// Store a range of words starting at the given address.
53    pub fn store_range(&mut self, address: Word, values: &[Word]) -> OpResult<()> {
54        let address = usize::try_from(address).map_err(|_| TemporaryError::IndexOutOfBounds)?;
55        let end = address
56            .checked_add(values.len())
57            .ok_or(TemporaryError::Overflow)?;
58        if end > self.0.len() {
59            return Err(TemporaryError::IndexOutOfBounds.into());
60        }
61        self.0[address..end].copy_from_slice(values);
62        Ok(())
63    }
64
65    /// Load a range of words starting at the given address.
66    pub fn load_range(&mut self, address: Word, size: Word) -> OpResult<Vec<Word>> {
67        let address = usize::try_from(address).map_err(|_| TemporaryError::IndexOutOfBounds)?;
68        let size = usize::try_from(size).map_err(|_| TemporaryError::Overflow)?;
69        let end = address.checked_add(size).ok_or(TemporaryError::Overflow)?;
70        if end > self.0.len() {
71            return Err(TemporaryError::IndexOutOfBounds.into());
72        }
73        Ok(self.0[address..end].to_vec())
74    }
75
76    /// Free some memory from an index to the end of this memory.
77    pub fn free(&mut self, address: Word) -> OpResult<()> {
78        let index = usize::try_from(address).map_err(|_| TemporaryError::IndexOutOfBounds)?;
79        if index >= self.0.len() {
80            return Err(TemporaryError::IndexOutOfBounds.into());
81        }
82        self.0.truncate(index);
83        self.0.shrink_to_fit();
84        Ok(())
85    }
86
87    /// Current len of the memory.
88    pub fn len(&self) -> OpResult<Word> {
89        Ok(self
90            .0
91            .len()
92            .try_into()
93            .map_err(|_| TemporaryError::Overflow)?)
94    }
95
96    /// Is the memory empty?
97    pub fn is_empty(&self) -> bool {
98        self.0.is_empty()
99    }
100}