use std::cell::RefCell; use memlib::{MemoryRead, MemoryReadExt, MemoryWrite, MemoryWriteExt}; /// An example memory source we will use to implement memlib traits onto. /// This can be replaced with an actual process in implementation. /// This needs to contain a RefCell to implement MemoryWrite because the trait only takes &self pub struct MemorySource(RefCell>); impl MemorySource { pub fn new() -> Self { Self(RefCell::new(vec![0xAB; 0x1000])) } } impl memlib::MemoryRead for MemorySource { fn try_read_bytes_into(&self, address: u64, buffer: &mut [u8]) -> Option<()> { let buf = self.0.borrow(); // Check if the read is out of bounds if address as usize + buffer.len() > buf.len() { return None; } // Copy the bytes from the source into the buffer buffer.copy_from_slice(&buf[address as usize..address as usize + buffer.len()]); Some(()) } } impl memlib::MemoryWrite for MemorySource { fn try_write_bytes(&self, address: u64, buffer: &[u8]) -> Option<()> { let buf = self.0.borrow_mut(); // Check if the write is out of bounds if address as usize + buffer.len() > self.0.len() { return None; } // Copy the bytes from the buffer into the source self.0.borrow_mut()[address as usize..address as usize + buffer.len()].copy_from_slice(buffer); Some(()) } } fn main() { // Create the memory source let memory_source = MemorySource::new(); // Read 4 bytes at offset 0x10 let mut buffer = [0u8; 4]; memory_source.try_read_bytes_into(0x10, &mut buffer).unwrap(); assert_eq!(buffer, [0xAB, 0xAB, 0xAB, 0xAB]); // We can also do this with the helper functions inside MemoryRead and MemoryReadExt use memlib::MemoryReadExt; let val = memory_source.read::(0x10); assert_eq!(val, 0xABABABAB); // Now let's write some bytes let buffer = [0xCD; 4]; memory_source.try_write_bytes(0x10, &buffer).unwrap(); // We can also write with the helper functions memory_source.write(0x10, &0xCDCDCDCD); let val = memory_source.read::(0x10); assert_eq!(val, 0xCDCDCDCD); } pub struct TestBuffer(*mut [u8]); impl TestBuffer { pub fn new() -> Self { Self(Box::into_raw(Box::new([0u8; 0x1000]))) } pub fn read_offset(&self, offset: u64) -> u8 { unsafe { if offset as usize >= (*self.0).len() { panic!("Out of bounds"); } (*self.0).as_ptr().offset(offset as isize).read_volatile() } } pub fn write_offset(&self, offset: u64, value: u8) { unsafe { if offset as usize >= (*self.0).len() { panic!("Out of bounds"); } (*self.0).as_ptr().offset(offset as isize).write_volatile(value) } } }