essential_vm/
memory.rs

1use essential_types::Word;
2
3use crate::error::MemoryError;
4
5#[cfg(test)]
6mod tests;
7
8#[derive(Clone, 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) -> Result<(), MemoryError> {
23        let size = usize::try_from(size).map_err(|_| MemoryError::Overflow)?;
24        let new_size = self
25            .0
26            .len()
27            .checked_add(size)
28            .ok_or(MemoryError::Overflow)?;
29        if new_size > Self::SIZE_LIMIT {
30            return Err(MemoryError::Overflow);
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) -> Result<(), MemoryError> {
38        let index = usize::try_from(address).map_err(|_| MemoryError::IndexOutOfBounds)?;
39        *self.0.get_mut(index).ok_or(MemoryError::IndexOutOfBounds)? = value;
40        Ok(())
41    }
42
43    /// Load a word from the given address.
44    pub fn load(&self, address: Word) -> Result<Word, MemoryError> {
45        let index = usize::try_from(address).map_err(|_| MemoryError::IndexOutOfBounds)?;
46        Ok(*self.0.get(index).ok_or(MemoryError::IndexOutOfBounds)?)
47    }
48
49    /// Store a range of words starting at the given address.
50    pub fn store_range(&mut self, address: Word, values: &[Word]) -> Result<(), MemoryError> {
51        let address = usize::try_from(address).map_err(|_| MemoryError::IndexOutOfBounds)?;
52        let end = address
53            .checked_add(values.len())
54            .ok_or(MemoryError::Overflow)?;
55        if end > self.0.len() {
56            return Err(MemoryError::IndexOutOfBounds);
57        }
58        self.0[address..end].copy_from_slice(values);
59        Ok(())
60    }
61
62    /// Load a range of words starting at the given address.
63    pub fn load_range(&self, address: Word, size: Word) -> Result<Vec<Word>, MemoryError> {
64        let address = usize::try_from(address).map_err(|_| MemoryError::IndexOutOfBounds)?;
65        let size = usize::try_from(size).map_err(|_| MemoryError::Overflow)?;
66        let end = address.checked_add(size).ok_or(MemoryError::Overflow)?;
67        if end > self.0.len() {
68            return Err(MemoryError::IndexOutOfBounds);
69        }
70        Ok(self.0[address..end].to_vec())
71    }
72
73    /// Truncate memory to the given `new_len`, freeing all memory that follows.
74    pub fn free(&mut self, new_len: Word) -> Result<(), MemoryError> {
75        let new_len = usize::try_from(new_len).map_err(|_| MemoryError::IndexOutOfBounds)?;
76        if new_len > self.0.len() {
77            return Err(MemoryError::IndexOutOfBounds);
78        }
79        self.0.truncate(new_len);
80        self.0.shrink_to_fit();
81        Ok(())
82    }
83
84    /// Current len of the memory.
85    pub fn len(&self) -> Result<Word, MemoryError> {
86        self.0.len().try_into().map_err(|_| MemoryError::Overflow)
87    }
88
89    /// Is the memory empty?
90    pub fn is_empty(&self) -> bool {
91        self.0.is_empty()
92    }
93}
94
95impl From<Memory> for Vec<Word> {
96    fn from(m: Memory) -> Vec<Word> {
97        m.0
98    }
99}
100
101impl TryFrom<Vec<Word>> for Memory {
102    type Error = MemoryError;
103    fn try_from(words: Vec<Word>) -> Result<Self, Self::Error> {
104        if words.len() > Self::SIZE_LIMIT {
105            Err(MemoryError::Overflow)
106        } else {
107            Ok(Self(words))
108        }
109    }
110}
111
112impl core::ops::Deref for Memory {
113    type Target = [Word];
114    fn deref(&self) -> &Self::Target {
115        &self.0
116    }
117}