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(
28 &self
29 .0
30 .iter()
31 .map(|r| ReportDebugHelper(r))
32 .collect::<Vec<_>>(),
33 )
34 .finish()
35 }
36}
37
38#[cfg(feature = "std")]
39impl Default for DistinctReports {
40 fn default() -> Self {
41 Self::new()
42 }
43}
44
45#[cfg(feature = "std")]
46impl core::cmp::PartialEq for DistinctReports {
47 fn eq(&self, other: &Self) -> bool {
48 if self.0[0] != other.0[0] {
50 return false;
51 }
52
53 let mut i: usize = 1;
54 let mut j: usize = 1;
55
56 let self_len = self.0.len();
57 let other_len = other.0.len();
58
59 while i < self_len && j < other_len {
61 while (i < self_len - 1) && self.0[i] == [0; 8] {
64 i += 1;
65 }
66 while (j < other_len - 1) && other.0[j] == [0; 8] {
67 j += 1;
68 }
69
70 if self.0[i] != other.0[j] {
71 if i > 0
75 && i < self_len - 1
76 && self.0[i + 1] == other.0[j]
77 && ((self.0[i - 1][0] == self.0[i][0] && self.0[i][2..] == self.0[i + 1][2..])
78 || (self.0[i - 1][2..] == self.0[i][2..]
79 && self.0[i][0] == self.0[i + 1][0]))
80 {
81 i += 1;
83 } else if j > 0
84 && j < other_len - 1
85 && self.0[i] == other.0[j + 1]
86 && ((other.0[j - 1][0] == other.0[j][0]
87 && other.0[j][2..] == other.0[j + 1][2..])
88 || (other.0[j - 1][2..] == other.0[j][2..]
89 && other.0[j][0] == other.0[j + 1][0]))
90 {
91 j += 1;
93 } else {
94 return false;
95 }
96 }
97
98 i += 1;
99 j += 1;
100 }
101
102 i == self_len && j == other_len
103 }
104}
105
106#[cfg(feature = "std")]
107impl DistinctReports {
108 pub fn new() -> Self {
110 Self(vec![[0; 8]])
111 }
112
113 pub fn update(&mut self, report: [u8; 8]) {
115 match self.0.last() {
116 Some(last_report) if last_report == &report => {}
117 _ => self.0.push(report),
118 }
119 }
120
121 pub fn reports(&self) -> &[[u8; 8]] {
123 self.0.as_slice()
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130
131 #[test]
132 fn test_distinct_reports_equal() {
133 let lhs = DistinctReports(vec![[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0x04, 0, 0, 0, 0, 0]]);
135 let rhs = DistinctReports(vec![[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0x04, 0, 0, 0, 0, 0]]);
136
137 assert!(lhs == rhs);
141 }
142
143 #[test]
144 fn test_distinct_reports_not_equal() {
145 let lhs = DistinctReports(vec![[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0x04, 0, 0, 0, 0, 0]]);
147 let rhs = DistinctReports(vec![[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0x05, 0, 0, 0, 0, 0]]);
148
149 assert!(lhs != rhs);
153 }
154
155 #[test]
156 fn test_distinct_reports_not_equal_modif() {
157 let lhs = DistinctReports(vec![[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0x04, 0, 0, 0, 0, 0]]);
159 let rhs = DistinctReports(vec![
160 [0, 0, 0, 0, 0, 0, 0, 0],
161 [0x01, 0, 0x04, 0, 0, 0, 0, 0],
162 ]);
163
164 assert!(lhs != rhs);
168 }
169
170 #[test]
171 fn test_distinct_reports_equal_ignores_0_between() {
172 let lhs = DistinctReports(vec![
174 [0, 0, 0, 0, 0, 0, 0, 0],
175 [0, 0, 0x04, 0, 0, 0, 0, 0],
176 [0, 0, 0x05, 0, 0, 0, 0, 0],
177 ]);
178 let rhs = DistinctReports(vec![
179 [0, 0, 0, 0, 0, 0, 0, 0],
180 [0, 0, 0x04, 0, 0, 0, 0, 0],
181 [0, 0, 0, 0, 0, 0, 0, 0],
182 [0, 0, 0x05, 0, 0, 0, 0, 0],
183 ]);
184
185 assert!(lhs == rhs);
189 }
190
191 #[test]
192 fn test_distinct_reports_not_equal_respects_trailing_0() {
193 let lhs = DistinctReports(vec![
195 [0, 0, 0, 0, 0, 0, 0, 0],
196 [0, 0, 0x04, 0, 0, 0, 0, 0],
197 [0, 0, 0x05, 0, 0, 0, 0, 0],
198 [0, 0, 0, 0, 0, 0, 0, 0],
199 ]);
200 let rhs = DistinctReports(vec![
201 [0, 0, 0, 0, 0, 0, 0, 0],
202 [0, 0, 0x04, 0, 0, 0, 0, 0],
203 [0, 0, 0, 0, 0, 0, 0, 0],
204 [0, 0, 0x05, 0, 0, 0, 0, 0],
205 ]);
206
207 assert!(lhs != rhs);
211 }
212
213 #[test]
214 fn test_distinct_reports_update_ignores_consecutive_duplicate() {
215 let lhs = DistinctReports(vec![[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0x04, 0, 0, 0, 0, 0]]);
217
218 let mut rhs = DistinctReports::new();
220 rhs.update([0, 0, 0x04, 0, 0, 0, 0, 0]);
221 rhs.update([0, 0, 0x04, 0, 0, 0, 0, 0]);
222 rhs.update([0, 0, 0x04, 0, 0, 0, 0, 0]);
223
224 assert!(lhs == rhs);
226 }
227
228 #[test]
229 fn test_distinct_reports_allows_modifier_press_equivalence() {
230 let lhs = DistinctReports(vec![
232 [0, 0, 0, 0, 0, 0, 0, 0],
233 [0x01, 0, 0x04, 0, 0, 0, 0, 0],
234 ]);
235 let rhs = DistinctReports(vec![
236 [0, 0, 0, 0, 0, 0, 0, 0],
237 [0x01, 0, 0, 0, 0, 0, 0, 0],
238 [0x01, 0, 0x04, 0, 0, 0, 0, 0],
239 ]);
240
241 assert!(lhs == rhs);
245 }
246
247 #[test]
248 fn test_distinct_reports_allows_modifier_release_equivalence() {
249 let lhs = DistinctReports(vec![
251 [0, 0, 0, 0, 0, 0, 0, 0],
252 [0x01, 0, 0x04, 0, 0, 0, 0, 0],
253 [0, 0, 0, 0, 0, 0, 0, 0],
254 ]);
255 let rhs = DistinctReports(vec![
256 [0, 0, 0, 0, 0, 0, 0, 0],
257 [0x01, 0, 0, 0, 0, 0, 0, 0],
258 [0x01, 0, 0x04, 0, 0, 0, 0, 0],
259 [0x01, 0, 0, 0, 0, 0, 0, 0],
260 [0, 0, 0, 0, 0, 0, 0, 0],
261 ]);
262
263 assert!(lhs == rhs);
267 }
268}