memacc/memman/
modify_address_value.rs

1use super::ReadFromAddress;
2use super::WriteToAddress;
3
4pub trait ModifyAddressValue {
5    type Word;
6    fn modify_address_value<F>(self, f: F)
7    where
8        F: FnOnce(&Self::Word) -> Self::Word;
9}
10
11/// Implement [`ModifyAddressValue`] for given type.
12macro_rules! ImplementModifyAddressValue {
13    ($type:ty) => {
14        impl ModifyAddressValue for *mut $type {
15            type Word = $type;
16            #[inline]
17            fn modify_address_value<F>(self, f: F)
18            where
19                F: FnOnce(&Self::Word) -> Self::Word,
20            {
21                let value_old = self.read_from_address();
22                let value_new = f(&value_old);
23                self.write_to_address(value_new);
24            }
25        }
26    };
27}
28
29ImplementModifyAddressValue!(u8);
30ImplementModifyAddressValue!(u16);
31ImplementModifyAddressValue!(u32);
32ImplementModifyAddressValue!(u64);
33
34#[cfg(test)]
35mod tests {
36    use crate::bitman::SetBit;
37    use crate::bitman::SetBits;
38    use crate::memman::ReadFromAddress;
39
40    use super::ModifyAddressValue;
41
42    #[test]
43    fn test_modify_address_value_0() {
44        let mut value = 0b0000_0000u8;
45        let reference = &mut value;
46        let address = reference as *mut u8;
47        address.modify_address_value(|w| w.set_bit(0));
48        assert_eq!(address.read_from_address(), 0b0000_0001);
49    }
50
51    #[test]
52    fn test_modify_address_value_1() {
53        let mut value = 0b0000_0000u8;
54        let reference = &mut value;
55        let address = reference as *mut u8;
56        address.modify_address_value(|w| w.set_bits(0..=1));
57        assert_eq!(address.read_from_address(), 0b0000_0011);
58    }
59
60    #[test]
61    fn test_modify_address_value_2() {
62        let mut value = 0b0000_0000u8;
63        let reference = &mut value;
64        let address = reference as *mut u8;
65        let action = |w: &u8| w.set_bit(0);
66        address.modify_address_value(action);
67        assert_eq!(address.read_from_address(), 0b0000_0001);
68    }
69
70    #[test]
71    fn test_modify_address_value_3() {
72        let mut value = 0b0000_0000u8;
73        let reference = &mut value;
74        let address = reference as *mut u8;
75        let action = |w: &u8| w.set_bits(0..=1);
76        address.modify_address_value(action);
77        assert_eq!(address.read_from_address(), 0b0000_0011);
78    }
79}