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
90
91
92
93
94
95
96
97
use std::marker::PhantomData;
use std::fmt;


/// Generic trait for objects that can track whether they've been read from and/or written to.
pub trait ReadWritable {
    /// Check if this object was read from.
    fn was_read(&self) -> bool;

    /// Check if this object was written to.
    fn was_written(&self) -> bool;

    /// Reset the R/W marking of this object.
    fn reset_rw(&mut self);
}


/// Marker for wrapper types that need to track when they were read from/written to.
///
/// # Examples
///
/// ```
/// # use pir_8_emu::ReadWriteMarker;
/// let marker = ReadWriteMarker::new();
///
/// assert_eq!(marker.was_read(), false);
/// assert_eq!(marker.was_written(), false);
///
/// marker.read();
/// assert_eq!(marker.was_read(), true);
///
/// let mut marker = marker;
/// marker.written();
/// assert_eq!(marker.was_written(), true);
///
/// marker.reset();
/// assert_eq!(marker.was_read(), false);
/// assert_eq!(marker.was_written(), false);
/// ```
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct ReadWriteMarker {
    mask: u8,
    _not_send_nor_sync: PhantomData<*const ()>,
}

impl ReadWriteMarker {
    /// Create a new unread and unwritten marker.
    pub fn new() -> ReadWriteMarker {
        ReadWriteMarker {
            mask: 0b00,
            _not_send_nor_sync: PhantomData,
        }
    }

    /// Mark this marker read.
    pub fn read(&self) {
        unsafe {
            *(&self.mask as *const u8 as *mut u8) |= 0b01;
        }
    }

    /// Mark this marker written.
    pub fn written(&mut self) {
        self.mask |= 0b10;
    }


    /// Check if this marker was marked read.
    pub fn was_read(self) -> bool {
        (self.mask & 0b01) != 0
    }

    /// Check if this marker was marked written.
    pub fn was_written(self) -> bool {
        (self.mask & 0b10) != 0
    }

    /// Reset the marker to its original unread and unwritten state.
    pub fn reset(&mut self) {
        self.mask = 0b00;
    }
}

impl Default for ReadWriteMarker {
    fn default() -> ReadWriteMarker {
        ReadWriteMarker::new()
    }
}

impl fmt::Debug for ReadWriteMarker {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("ReadWriteMarker")
            .field("read", &((self.mask & 0b01) != 0))
            .field("written", &((self.mask & 0b10) != 0))
            .finish()
    }
}