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.push(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); } } eprintln!("tried to allocate {:X} but there are no more pages!", virtual_addr); None } 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); } } 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); } } println!("virtual_addr {:X} is not allocated", virtual_addr); 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(page, permission) { self.memory[self.pages[page].real_addr + offset] = value; return Ok(()); } 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(page, permission) { Ok(self.memory[self.pages[page].real_addr + offset]) } else { println!("address {:X} is not allocated", address); Err(()) } } pub fn read_multiple_bytes( &self, address: usize, size: usize, permission: usize, ) -> Result, ()> { let mut ret = vec![0; size]; for addr in address..address + size { if let Ok(byte) = self.read(addr, permission) { ret[addr - address] = byte; } else { return Err(()); } } Ok(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(()) } }