serial.rs

 1use std::time::Instant;
 2
 3use collections::HashMap;
 4
 5#[derive(Debug, Hash, PartialEq, Eq)]
 6pub(crate) enum SerialKind {
 7    DataDevice,
 8    InputMethod,
 9    MouseEnter,
10    MousePress,
11    KeyPress,
12}
13
14#[derive(Debug)]
15struct SerialData {
16    serial: u32,
17    time: Instant,
18}
19
20impl SerialData {
21    fn new(value: u32) -> Self {
22        Self {
23            serial: value,
24            time: Instant::now(),
25        }
26    }
27}
28
29#[derive(Debug)]
30/// Helper for tracking of different serial kinds.
31pub(crate) struct SerialTracker {
32    serials: HashMap<SerialKind, SerialData>,
33}
34
35impl SerialTracker {
36    pub fn new() -> Self {
37        Self {
38            serials: HashMap::default(),
39        }
40    }
41
42    pub fn update(&mut self, kind: SerialKind, value: u32) {
43        self.serials.insert(kind, SerialData::new(value));
44    }
45
46    /// Returns the latest tracked serial of the provided [`SerialKind`]
47    ///
48    /// Will return 0 if not tracked.
49    pub fn get(&self, kind: SerialKind) -> u32 {
50        self.serials
51            .get(&kind)
52            .map(|serial_data| serial_data.serial)
53            .unwrap_or(0)
54    }
55
56    /// Returns the newest serial of any of the provided [`SerialKind`]
57    pub fn get_newest_of(&self, kinds: &[SerialKind]) -> u32 {
58        kinds
59            .iter()
60            .filter_map(|kind| self.serials.get(&kind))
61            .max_by_key(|serial_data| serial_data.time)
62            .map(|serial_data| serial_data.serial)
63            .unwrap_or(0)
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn test_serial_tracker() {
73        let mut tracker = SerialTracker::new();
74
75        tracker.update(SerialKind::KeyPress, 100);
76        tracker.update(SerialKind::MousePress, 50);
77        tracker.update(SerialKind::MouseEnter, 300);
78
79        assert_eq!(
80            tracker.get_newest_of(&[SerialKind::KeyPress, SerialKind::MousePress]),
81            50
82        );
83        assert_eq!(tracker.get(SerialKind::DataDevice), 0);
84
85        tracker.update(SerialKind::KeyPress, 2000);
86        assert_eq!(tracker.get(SerialKind::KeyPress), 2000);
87        assert_eq!(
88            tracker.get_newest_of(&[SerialKind::KeyPress, SerialKind::MousePress]),
89            2000
90        );
91    }
92}