1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//use mockall::predicate::*;
//use mockall::*;
//use modular_bitfield::prelude::*;
use std::convert::TryInto;
use std::result::Result;

//#[automock]
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>;
}

/*#[automock]
pub trait RegmapAccessor64Bit {
    type Error;

    fn peek64(&mut self, addr: u64) -> u64;
    fn poke64(&mut self, addr: u64, data: u64);
}*/

/*#[automock]
pub trait RegmapAccessor<T: Copy> {
    fn peek(&mut self, addr: T) -> T;
    fn poke(&mut self, addr: T, data: T);
}*/

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);
    }
}