1use std::convert::TryInto;
5use std::result::Result;
6
7pub trait RegmapAccessor<T> {
9 type Error;
10
11 fn peek(&mut self, addr: T) -> Result<T, Self::Error>;
12 fn poke(&mut self, addr: T, data: T) -> Result<(), Self::Error>;
13}
14
15pub struct MemoryAccessor {
30 base: *mut u8,
31}
32
33impl MemoryAccessor {
34 pub fn new(base: usize) -> MemoryAccessor {
35 MemoryAccessor {
36 base: base as *mut u8,
37 }
38 }
39}
40
41impl RegmapAccessor<u32> for MemoryAccessor {
42 type Error = ();
43
44 fn peek(&mut self, addr: u32) -> Result<u32, Self::Error> {
45 unsafe {
46 let ptr = self.base.offset(
47 addr.try_into()
48 .expect("Couldn't convert offset into isize in peek32"),
49 ) as *mut u32;
50 Ok(*ptr)
51 }
52 }
53
54 fn poke(&mut self, addr: u32, data: u32) -> Result<(), Self::Error> {
55 unsafe {
56 let ptr = self.base.offset(
57 addr.try_into()
58 .expect("Couldn't convert offset into isize in poke32"),
59 ) as *mut u32;
60 *ptr = data;
61 }
62 Ok(())
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::{MemoryAccessor, RegmapAccessor32Bit};
69 use std::convert::TryInto;
70
71 #[test]
72 fn can_peek() {
73 let mut backing = vec![0u8; 1024];
74 backing[12] = 5;
75 let mut accessor = MemoryAccessor::new(backing.as_ptr() as usize);
76 assert_eq!(accessor.peek32(12), 5);
77 }
78
79 #[test]
80 fn can_poke() {
81 let backing = vec![0u8; 1024];
82 let mut accessor = MemoryAccessor::new(backing.as_ptr() as usize);
83 accessor.poke32(40, 0x12345678);
84 assert_eq!(backing[40 + 0], 0x78);
85 assert_eq!(backing[40 + 1], 0x56);
86 assert_eq!(backing[40 + 2], 0x34);
87 assert_eq!(backing[40 + 3], 0x12);
88 }
89}