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}