1use core::fmt::Debug;
2
3#[cfg(feature = "std")]
5#[derive(Clone, Eq)]
6pub struct DistinctReports(Vec<[u8; 8]>);
7
8#[cfg(feature = "std")]
9struct ReportDebugHelper<'a>(&'a [u8; 8]);
10
11#[cfg(feature = "std")]
12impl Debug for ReportDebugHelper<'_> {
13 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14 write!(
15 f,
16 "[{:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X}]",
17 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], self.0[6], self.0[7]
18 )
19 }
20}
21
22#[cfg(feature = "std")]
23impl Debug for DistinctReports {
24 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
25 f.debug_tuple("DistinctReports")
27 .field(&self.0.iter().map(ReportDebugHelper).collect::<Vec<_>>())
28 .finish()
29 }
30}
31
32#[cfg(feature = "std")]
33impl Default for DistinctReports {
34 fn default() -> Self {
35 Self::new()
36 }
37}
38
39#[cfg(feature = "std")]
40impl core::cmp::PartialEq for DistinctReports {
41 fn eq(&self, other: &Self) -> bool {
42 if self.0[0] != other.0[0] {
44 return false;
45 }
46
47 let mut i: usize = 1;
48 let mut j: usize = 1;
49
50 let self_len = self.0.len();
51 let other_len = other.0.len();
52
53 while i < self_len && j < other_len {
55 while (i < self_len - 1) && self.0[i] == [0; 8] {
58 i += 1;
59 }
60 while (j < other_len - 1) && other.0[j] == [0; 8] {
61 j += 1;
62 }
63
64 if self.0[i] != other.0[j] {
65 if i > 0
69 && i < self_len - 1
70 && self.0[i + 1] == other.0[j]
71 && ((self.0[i - 1][0] == self.0[i][0] && self.0[i][2..] == self.0[i + 1][2..])
72 || (self.0[i - 1][2..] == self.0[i][2..]
73 && self.0[i][0] == self.0[i + 1][0]))
74 {
75 i += 1;
77 } else if j > 0
78 && j < other_len - 1
79 && self.0[i] == other.0[j + 1]
80 && ((other.0[j - 1][0] == other.0[j][0]
81 && other.0[j][2..] == other.0[j + 1][2..])
82 || (other.0[j - 1][2..] == other.0[j][2..]
83 && other.0[j][0] == other.0[j + 1][0]))
84 {
85 j += 1;
87 } else {
88 return false;
89 }
90 }
91
92 i += 1;
93 j += 1;
94 }
95
96 i == self_len && j == other_len
97 }
98}
99
100#[cfg(feature = "std")]
101impl DistinctReports {
102 pub fn new() -> Self {
104 Self(vec![[0; 8]])
105 }
106
107 pub fn update(&mut self, report: [u8; 8]) {
109 match self.0.last() {
110 Some(last_report) if last_report == &report => {}
111 _ => self.0.push(report),
112 }
113 }
114
115 pub fn reports(&self) -> &[[u8; 8]] {
117 self.0.as_slice()
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124
125 #[test]
126 fn test_distinct_reports_equal() {
127 let lhs = DistinctReports(vec![[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0x04, 0, 0, 0, 0, 0]]);
129 let rhs = DistinctReports(vec![[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0x04, 0, 0, 0, 0, 0]]);
130
131 assert!(lhs == rhs);
135 }
136
137 #[test]
138 fn test_distinct_reports_not_equal() {
139 let lhs = DistinctReports(vec![[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0x04, 0, 0, 0, 0, 0]]);
141 let rhs = DistinctReports(vec![[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0x05, 0, 0, 0, 0, 0]]);
142
143 assert!(lhs != rhs);
147 }
148
149 #[test]
150 fn test_distinct_reports_not_equal_modif() {
151 let lhs = DistinctReports(vec![[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0x04, 0, 0, 0, 0, 0]]);
153 let rhs = DistinctReports(vec![
154 [0, 0, 0, 0, 0, 0, 0, 0],
155 [0x01, 0, 0x04, 0, 0, 0, 0, 0],
156 ]);
157
158 assert!(lhs != rhs);
162 }
163
164 #[test]
165 fn test_distinct_reports_equal_ignores_0_between() {
166 let lhs = DistinctReports(vec![
168 [0, 0, 0, 0, 0, 0, 0, 0],
169 [0, 0, 0x04, 0, 0, 0, 0, 0],
170 [0, 0, 0x05, 0, 0, 0, 0, 0],
171 ]);
172 let rhs = DistinctReports(vec![
173 [0, 0, 0, 0, 0, 0, 0, 0],
174 [0, 0, 0x04, 0, 0, 0, 0, 0],
175 [0, 0, 0, 0, 0, 0, 0, 0],
176 [0, 0, 0x05, 0, 0, 0, 0, 0],
177 ]);
178
179 assert!(lhs == rhs);
183 }
184
185 #[test]
186 fn test_distinct_reports_not_equal_respects_trailing_0() {
187 let lhs = DistinctReports(vec![
189 [0, 0, 0, 0, 0, 0, 0, 0],
190 [0, 0, 0x04, 0, 0, 0, 0, 0],
191 [0, 0, 0x05, 0, 0, 0, 0, 0],
192 [0, 0, 0, 0, 0, 0, 0, 0],
193 ]);
194 let rhs = DistinctReports(vec![
195 [0, 0, 0, 0, 0, 0, 0, 0],
196 [0, 0, 0x04, 0, 0, 0, 0, 0],
197 [0, 0, 0, 0, 0, 0, 0, 0],
198 [0, 0, 0x05, 0, 0, 0, 0, 0],
199 ]);
200
201 assert!(lhs != rhs);
205 }
206
207 #[test]
208 fn test_distinct_reports_update_ignores_consecutive_duplicate() {
209 let lhs = DistinctReports(vec![[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0x04, 0, 0, 0, 0, 0]]);
211
212 let mut rhs = DistinctReports::new();
214 rhs.update([0, 0, 0x04, 0, 0, 0, 0, 0]);
215 rhs.update([0, 0, 0x04, 0, 0, 0, 0, 0]);
216 rhs.update([0, 0, 0x04, 0, 0, 0, 0, 0]);
217
218 assert!(lhs == rhs);
220 }
221
222 #[test]
223 fn test_distinct_reports_allows_modifier_press_equivalence() {
224 let lhs = DistinctReports(vec![
226 [0, 0, 0, 0, 0, 0, 0, 0],
227 [0x01, 0, 0x04, 0, 0, 0, 0, 0],
228 ]);
229 let rhs = DistinctReports(vec![
230 [0, 0, 0, 0, 0, 0, 0, 0],
231 [0x01, 0, 0, 0, 0, 0, 0, 0],
232 [0x01, 0, 0x04, 0, 0, 0, 0, 0],
233 ]);
234
235 assert!(lhs == rhs);
239 }
240
241 #[test]
242 fn test_distinct_reports_allows_modifier_release_equivalence() {
243 let lhs = DistinctReports(vec![
245 [0, 0, 0, 0, 0, 0, 0, 0],
246 [0x01, 0, 0x04, 0, 0, 0, 0, 0],
247 [0, 0, 0, 0, 0, 0, 0, 0],
248 ]);
249 let rhs = DistinctReports(vec![
250 [0, 0, 0, 0, 0, 0, 0, 0],
251 [0x01, 0, 0, 0, 0, 0, 0, 0],
252 [0x01, 0, 0x04, 0, 0, 0, 0, 0],
253 [0x01, 0, 0, 0, 0, 0, 0, 0],
254 [0, 0, 0, 0, 0, 0, 0, 0],
255 ]);
256
257 assert!(lhs == rhs);
261 }
262}