use std::convert::TryInto;
use std::result::Result;
pub trait RegmapAccessor<T> {
type Error;
fn peek(&mut self, addr: T) -> Result<T, Self::Error>;
fn poke(&mut self, addr: T, data: T) -> Result<(), Self::Error>;
}
pub struct MemoryAccessor {
base: *mut u8,
}
impl MemoryAccessor {
pub fn new(base: usize) -> MemoryAccessor {
MemoryAccessor {
base: base as *mut u8,
}
}
}
impl RegmapAccessor<u32> for MemoryAccessor {
type Error = ();
fn peek(&mut self, addr: u32) -> Result<u32, Self::Error> {
unsafe {
let ptr = self.base.offset(
addr.try_into()
.expect("Couldn't convert offset into isize in peek32"),
) as *mut u32;
Ok(*ptr)
}
}
fn poke(&mut self, addr: u32, data: u32) -> Result<(), Self::Error> {
unsafe {
let ptr = self.base.offset(
addr.try_into()
.expect("Couldn't convert offset into isize in poke32"),
) as *mut u32;
*ptr = data;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::{MemoryAccessor, RegmapAccessor32Bit};
use std::convert::TryInto;
#[test]
fn can_peek() {
let mut backing = vec![0u8; 1024];
backing[12] = 5;
let mut accessor = MemoryAccessor::new(backing.as_ptr() as usize);
assert_eq!(accessor.peek32(12), 5);
}
#[test]
fn can_poke() {
let backing = vec![0u8; 1024];
let mut accessor = MemoryAccessor::new(backing.as_ptr() as usize);
accessor.poke32(40, 0x12345678);
assert_eq!(backing[40 + 0], 0x78);
assert_eq!(backing[40 + 1], 0x56);
assert_eq!(backing[40 + 2], 0x34);
assert_eq!(backing[40 + 3], 0x12);
}
}