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