wasm_dbms_memory/
provider.rs1use wasm_dbms_api::prelude::{MemoryError, MemoryResult};
4
5pub const WASM_PAGE_SIZE: u64 = 65536;
7
8pub trait MemoryProvider {
13 const PAGE_SIZE: u64;
15
16 fn size(&self) -> u64;
18
19 fn pages(&self) -> u64;
21
22 fn grow(&mut self, new_pages: u64) -> MemoryResult<u64>;
28
29 fn read(&self, offset: u64, buf: &mut [u8]) -> MemoryResult<()>;
33
34 fn write(&mut self, offset: u64, buf: &[u8]) -> MemoryResult<()>;
38}
39
40#[derive(Debug, Default)]
42pub struct HeapMemoryProvider {
43 memory: Vec<u8>,
44}
45
46impl MemoryProvider for HeapMemoryProvider {
47 const PAGE_SIZE: u64 = WASM_PAGE_SIZE; fn grow(&mut self, new_pages: u64) -> MemoryResult<u64> {
50 let previous_size = self.size();
51 let additional_size = (new_pages * Self::PAGE_SIZE) as usize;
52 self.memory
53 .resize(previous_size as usize + additional_size, 0);
54 Ok(previous_size)
55 }
56
57 fn size(&self) -> u64 {
58 self.memory.len() as u64
59 }
60
61 fn pages(&self) -> u64 {
62 self.size() / Self::PAGE_SIZE
63 }
64
65 fn read(&self, offset: u64, buf: &mut [u8]) -> MemoryResult<()> {
66 if offset + buf.len() as u64 > self.size() {
68 return Err(MemoryError::OutOfBounds);
69 }
70
71 buf.copy_from_slice(&self.memory[offset as usize..(offset as usize + buf.len())]);
72 Ok(())
73 }
74
75 fn write(&mut self, offset: u64, buf: &[u8]) -> MemoryResult<()> {
76 if offset + buf.len() as u64 > self.size() {
78 return Err(MemoryError::OutOfBounds);
79 }
80
81 self.memory[offset as usize..(offset as usize + buf.len())].copy_from_slice(buf);
82 Ok(())
83 }
84}
85
86#[cfg(test)]
87mod tests {
88
89 use super::*;
90
91 #[test]
92 fn test_should_grow_heap_memory() {
93 let mut provider = HeapMemoryProvider::default();
94 assert_eq!(provider.size(), 0);
95
96 let previous_size = provider.grow(2).unwrap();
97 assert_eq!(previous_size, 0);
98 assert_eq!(provider.size(), 2 * HeapMemoryProvider::PAGE_SIZE);
99
100 let previous_size = provider.grow(1).unwrap();
101 assert_eq!(previous_size, 2 * HeapMemoryProvider::PAGE_SIZE);
102 assert_eq!(provider.size(), 3 * HeapMemoryProvider::PAGE_SIZE);
103 }
104
105 #[test]
106 fn test_should_read_and_write_heap_memory() {
107 let mut provider = HeapMemoryProvider::default();
108 provider.grow(1).unwrap(); let data_to_write = vec![1, 2, 3, 4, 5];
110 provider.write(0, &data_to_write).unwrap();
111 let mut buffer = vec![0; 5];
112 provider.read(0, &mut buffer).unwrap();
113 assert_eq!(buffer, data_to_write);
114 }
115
116 #[test]
117 fn test_should_not_read_out_of_bounds_heap_memory() {
118 let mut provider = HeapMemoryProvider::default();
119 provider.grow(1).unwrap(); let mut buffer = vec![0; 10];
121 let result = provider.read(HeapMemoryProvider::PAGE_SIZE - 5, &mut buffer);
122 assert!(result.is_err());
123 assert!(matches!(result.err().unwrap(), MemoryError::OutOfBounds));
124 }
125
126 #[test]
127 fn test_should_not_write_out_of_bounds_heap_memory() {
128 let mut provider = HeapMemoryProvider::default();
129 provider.grow(1).unwrap(); let data_to_write = vec![1, 2, 3, 4, 5];
131 let result = provider.write(HeapMemoryProvider::PAGE_SIZE - 3, &data_to_write);
132 assert!(result.is_err());
133 assert!(matches!(result.err().unwrap(), MemoryError::OutOfBounds));
134 }
135
136 #[test]
137 fn test_should_get_amount_of_pages_heap_memory() {
138 let mut provider = HeapMemoryProvider::default();
139 assert_eq!(provider.pages(), 0);
140
141 provider.grow(3).unwrap(); assert_eq!(provider.pages(), 3);
143
144 provider.grow(2).unwrap(); assert_eq!(provider.pages(), 5);
146 }
147}