osiris_data/
memory.rs

1//! This module define the [Memory] struct and its implementation.
2
3use std::ops::{Index, IndexMut};
4
5use crate::data::atomic::Word;
6use crate::data::composite::Array;
7use crate::data::identification::{Address, Area, Identifier};
8
9/// Describes the full memory available for a machine.
10#[derive(Clone, Default, Debug)]
11pub struct Memory {
12    data: Vec<Word>,
13}
14
15/// Represents an error occurring during a memory operation.
16#[derive(Debug)]
17pub enum MemoryError {
18    /// A memory operation requested a position out of valid (allocated) memory.
19    OutOfBounds { requested: usize, memory_len: usize },
20    /// Requested to free more memory than allocated.
21    CannotFree { trying_to_free: usize, memory_len: usize },
22}
23
24/// The result of some memory operations which can fail.
25pub type MemoryResult<T> = Result<T, MemoryError>;
26
27impl Memory {
28    /// Creates an empty (no allocation) memory.
29    pub fn new() -> Self { Self::default() }
30
31    /// Creates a memory with an arbitrary size.
32    pub fn with_size(size: usize) -> Self {
33        let mut mem = Self::default();
34        mem.data.resize(size, Word::default());
35        mem
36    }
37
38    /// The total memory size.
39    pub fn len(&self) -> usize { self.data.len() }
40    
41    /// Returns `true` if the size of the memory is 0. 
42    pub fn is_empty(&self) -> bool { self.data.is_empty() }
43
44    /// Write a [Word] into the memory at the specified [Address].
45    pub fn store(&mut self, address: Address, datum: Word) -> MemoryResult<()> {
46        if address.to_usize() >= self.data.len() {
47            Err(MemoryError::OutOfBounds { requested: address.to_usize(), memory_len: self.len() })
48        } else {
49            self.data[address.to_usize()] = datum;
50            Ok(())
51        }
52    }
53
54    /// Reads a [Word] from the memory at the specified [Address].
55    pub fn load(&self, address: Address) -> MemoryResult<Word> {
56        if address.to_usize() >= self.data.len() {
57            Err(MemoryError::OutOfBounds { requested: address.to_usize(), memory_len: self.len() })
58        } else {
59            Ok(self.data[address.to_usize()])
60        }
61    }
62
63    /// Reads a full [Array] from the memory between the specified [Address]es.
64    pub fn array(&self, area: Area) -> MemoryResult<Array> {
65        let slice = self.slice(area)?;
66        Ok(Array::from(slice))
67    }
68
69    /// Reads a full sliced-[Array] from the memory between the specified [Address]es.
70    pub fn slice(&self, area: Area) -> MemoryResult<&[Word]> {
71        let start = area.start().to_usize();
72        let end = area.end().to_usize();
73        if start >= self.data.len() || end >= self.data.len() {
74            Err(MemoryError::OutOfBounds { requested: start.max(end), memory_len: self.len() })
75        } else {
76            Ok(&self.data[start..=end])
77        }
78    }
79
80    /// Writes a full [Array] into the memory to the specified [Address].
81    pub fn copy(&mut self, to: Address, data: Array) -> MemoryResult<()> {
82        let start = to.to_usize();
83        let end = start + data.len();
84        if start >= self.data.len() || end >= self.data.len() {
85            Err(MemoryError::OutOfBounds { requested: start.max(end), memory_len: self.len() })
86        } else {
87            let mut current = start;
88            for datum in data.iter() {
89                self.data[current] = *datum;
90                current += 1;
91            };
92            Ok(())
93        }
94    }
95
96    /// Grow the memory with the specified size.
97    pub fn alloc(&mut self, additional_size: usize) {
98        self.data.resize(self.data.len() + additional_size, Word::default());
99    }
100
101    /// Free the memory from the specified size.
102    pub fn free(&mut self, sub_size: usize) -> MemoryResult<()> {
103        if sub_size > self.data.len() {
104            return Err(MemoryError::CannotFree { trying_to_free: sub_size, memory_len: self.len() });
105        }
106        self.data.resize(self.data.len() - sub_size, Word::default());
107        Ok(())
108    }
109}
110
111impl Index<Address> for Memory {
112    type Output = Word;
113    fn index(&self, index: Address) -> &Self::Output { &self.data[index.to_usize()] }
114}
115
116impl IndexMut<Address> for Memory {
117    fn index_mut(&mut self, index: Address) -> &mut Self::Output { &mut self.data[index.to_usize()] }
118}