cubipods/
memory.rs

1use crate::utils::bytes32::Bytes32;
2
3#[derive(Debug)]
4pub struct Memory {
5    pub heap: Vec<u8>,
6}
7
8impl Default for Memory {
9    fn default() -> Self {
10        Self::new()
11    }
12}
13
14impl Memory {
15    pub fn new() -> Self {
16        Self { heap: vec![0; 0] }
17    }
18
19    fn extend(&mut self, size: usize) {
20        self.heap.extend(vec![0; size]);
21    }
22
23    /// Documentation
24    ///
25    /// # Safety
26    ///
27    /// As Memory::mload, it loads data from given location pointer.
28    pub unsafe fn mload(&mut self, location: Bytes32) -> Bytes32 {
29        let location: usize = location.try_into().unwrap();
30        let extended_location = location + 32;
31
32        if extended_location > self.heap.len() {
33            if location % 32 == 0 {
34                self.extend(extended_location - self.heap.len());
35            } else {
36                self.extend(extended_location + (location % 32) - self.heap.len());
37            };
38        }
39
40        let ptr = self.heap.as_ptr().add(location) as *const Bytes32;
41
42        unsafe { *ptr }
43    }
44
45    /// Documentation
46    ///
47    /// # Safety
48    ///
49    /// As Memory::mstore, it stores given data to given location pointer.
50    pub unsafe fn mstore(&mut self, location: Bytes32, data: Bytes32) {
51        let location: usize = location.try_into().unwrap();
52        let extended_location = location + 32;
53
54        if extended_location > self.heap.len() {
55            self.extend(extended_location - self.heap.len());
56        }
57
58        let ptr = self.heap.as_mut_ptr().add(location) as *mut [u8; 32];
59
60        *ptr = data.0;
61    }
62
63    /// Documentation
64    ///
65    /// # Safety
66    ///
67    /// As Memory::load_only, it loads data from given location pointer.
68    pub unsafe fn load_only(&self, location: Bytes32) -> Bytes32 {
69        let location: usize = location.try_into().unwrap();
70
71        let ptr = self.heap.as_ptr().add(location) as *const Bytes32;
72
73        unsafe { *ptr }
74    }
75
76    pub fn msize(&self) -> usize {
77        self.heap.len()
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn it_creates_memory_heap() {
87        let memory = Memory::new();
88
89        assert_eq!(memory.heap.is_empty(), true);
90    }
91
92    #[test]
93    fn it_extends_memory() {
94        let mut memory = Memory::new();
95
96        memory.extend(32);
97
98        assert_eq!(memory.heap.is_empty(), false);
99        assert_eq!(memory.msize(), 32);
100    }
101
102    #[test]
103    fn it_stores_and_loads_data_which_is_multiplication_of_32_in_memory() {
104        let mut memory = Memory::new();
105
106        let data = "ff1122".parse::<Bytes32>().unwrap();
107        let mem_location = Bytes32::from(0);
108
109        let result: Bytes32;
110        unsafe {
111            memory.mstore(mem_location, data);
112
113            result = memory.mload(mem_location);
114        }
115
116        assert_eq!(result, data);
117    }
118
119    #[test]
120    fn it_stores_and_loads_data_which_is_not_multiplication_of_32_in_memory() {
121        let mut memory = Memory::new();
122
123        let data = "ff1122".parse::<Bytes32>().unwrap();
124        let mem_location = Bytes32::from(37);
125        let mem_upper_limit = 37 + 32;
126
127        let result: Bytes32;
128        unsafe {
129            memory.mstore(mem_location, data);
130
131            result = memory.mload(mem_location);
132        }
133
134        assert_eq!(result, data);
135        assert_eq!(memory.msize(), mem_upper_limit);
136    }
137}