const PAGE_SIZE: usize = 4 * 1024; const PAGE_MASK: usize = !(PAGE_SIZE - 1); struct Page { virtual_addr: usize, real_addr: usize, permission: usize, allocated: usize, } pub struct Memory { memory: Box<[u8]>, pages: Vec, } impl Memory { pub fn new(size: usize) -> Memory { let mut pages: Vec = Vec::with_capacity(size / PAGE_SIZE); for i in 0..size / PAGE_SIZE { pages[i] = Page { virtual_addr: usize::MAX, real_addr: i * PAGE_SIZE, permission: 0, allocated: 0 } } Memory { memory: vec![0u8; size].into_boxed_slice(), pages, } } pub fn create_page(&mut self, virtual_addr: usize, permission: usize) -> Option { // Find first page that isn't allocated and set it to allocated for (i, page) in self.pages.iter_mut().enumerate() { if page.allocated == 0 { page.virtual_addr = virtual_addr; page.permission = permission; page.allocated = 1; return Some(i); } } None } pub fn lookup_page(&mut self, virtual_addr: usize, permission: usize) -> Option { for (i, page) in self.pages.iter().enumerate() { if page.virtual_addr == virtual_addr && permission >= page.permission && page.allocated == 1 { return Some(i); } } return self.create_page(virtual_addr, permission); } pub fn ro_lookup(&self, virtual_addr: usize, permission: usize) -> Option { for (i, page) in self.pages.iter().enumerate() { if page.virtual_addr == virtual_addr && page.permission == permission && page.allocated == 1 { return Some(i); } } None } pub fn write(&mut self, address: usize, permission: usize, value: u8) -> Result<(), ()> { let page = address & PAGE_MASK; let offset = address - page; if let Some(page) = self.lookup_page(address, permission) { self.memory[self.pages[page].real_addr + offset] = value; Ok(()) } else { Err(()) } } pub fn read(&self, address: usize, permission: usize) -> Result { let page = address & PAGE_MASK; let offset = address - page; if let Some(page) = self.ro_lookup(address, permission) { Ok(self.memory[self.pages[page].real_addr + offset]) } else { Err(()) } } pub fn read_multiple_bytes(&self, address: usize, size: usize, permission: usize) -> Result, ()> { let mut ret = []; for addr in address..address+size { if let Ok(byte) = self.read(addr, permission) { ret[addr - address] = byte; } else { return Err(()); } } Ok(Box::new(ret)) } pub fn write_multiple_bytes(&mut self, address: usize, bytes: &[u8], permission: usize) -> Result<(), ()> { for addr in address..address + bytes.len() { if let Err(_) = self.write(addr, permission, bytes[addr - address]) { return Err(()); } } Ok(()) } }