1use hid_types::encoding::{Size, TagTypeSize, TypeBits};
4use hid_types::hid::{CollectionType, InputFlags, IoFlags, OutputFeatureFlags, Unit};
5use hid_types::id::tag::{GlobalItem, LocalItem, MainItem};
6use hid_types::id::usage::UsagePage;
7use hid_types::item::usage::{ExtendedUsage, Usage};
8use hid_types::item::{Global, Item, Local, LongItem, Main};
9use tinyvec::TinyVec;
10
11#[derive(Default, Debug, Clone)]
13pub struct DecoderContext {
14 usage_page: Option<UsagePage>,
16}
17
18pub struct DecodedItem {
20 pub item: Item,
22 pub bytes: TinyVec<[u8; 8]>,
24}
25
26impl DecodedItem {
27 fn yes<T, E>(item: Item, iter: Recorder<T>) -> Result<Self, E> {
29 Ok(Self {
30 item,
31 bytes: iter.take_bytes(),
32 })
33 }
34}
35
36pub fn decode_one<Iter>(
40 iter: Iter,
41 context: &mut DecoderContext,
42) -> Option<Result<DecodedItem, LengthError>>
43where
44 Iter: Iterator<Item = u8>,
45{
46 let mut iter = Recorder::new(iter);
47
48 let Some(tag) = iter.next() else {
49 return None;
51 };
52 Some(decode_one_inner(iter, context, tag))
53}
54
55fn decode_one_inner<I>(
59 mut iter: Recorder<I>,
60 context: &mut DecoderContext,
61 tag: u8,
62) -> Result<DecodedItem, LengthError>
63where
64 I: Iterator<Item = u8>,
65{
66 let tag = TagTypeSize::from_bits(tag);
67
68 let more: TinyVec<[u8; 8]> = match tag.size() {
69 Size::Short(size_bytes) => {
70 let iter_remaining = (&mut iter).take(size_bytes);
71 iter_remaining.collect()
72 }
73 Size::Long => {
74 let (Some(size), Some(tag)) = (iter.next(), iter.next()) else {
75 return Err(LengthError::Truncated);
76 };
77 let iter_payload = (&mut iter).take(usize::from(size));
78 let data = iter_payload.collect::<Vec<_>>();
79 let item = Item::Long(LongItem { tag, data });
80 return DecodedItem::yes(item, iter);
81 }
82 };
83
84 match tag.ty() {
85 TypeBits::Main => {
86 let item = MainItem::from(tag.tag());
87 let decoded = match item {
88 MainItem::Input => {
89 let data = slice_to_u32(&more)?;
90 let flags = InputFlags(IoFlags::from(data));
91 Main::Input(flags)
92 }
93 MainItem::Output => {
94 let data = slice_to_u32(&more)?;
95 let flags = OutputFeatureFlags(IoFlags::from(data));
96 Main::Output(flags)
97 }
98 MainItem::Feature => {
99 let data = slice_to_u32(&more)?;
100 let flags = OutputFeatureFlags(IoFlags::from(data));
101 Main::Feature(flags)
102 }
103 MainItem::Collection => {
104 assert_eq!(more.len(), 1);
105 let coll_type = CollectionType::from_integer(more[0]);
106 Main::Collection(coll_type)
107 }
108 MainItem::EndCollection => {
109 assert!(more.is_empty());
110 Main::EndCollection
111 }
112 MainItem::Reserved => Main::Reserved(tag.tag()),
113 };
114 DecodedItem::yes(Item::Main(decoded), iter)
115 }
116 TypeBits::Global => {
117 let item = GlobalItem::from(tag.tag());
118 let decoded = match item {
119 GlobalItem::UsagePage => {
120 let page_number = slice_to_u16(&more)?;
121 let usage_page = UsagePage::from_integer(page_number);
122 context.usage_page = Some(usage_page);
123 Global::UsagePage(usage_page)
124 }
125 GlobalItem::LogicalMinimum => {
126 let num = slice_to_i32(&more)?;
127 Global::LogicalMinimum(num)
128 }
129 GlobalItem::LogicalMaximum => {
130 let num = slice_to_i32(&more)?;
131 Global::LogicalMaximum(num)
132 }
133 GlobalItem::PhysicalMinimum => {
134 let num = slice_to_i32(&more)?;
135 Global::PhysicalMinimum(num)
136 }
137 GlobalItem::PhysicalMaximum => {
138 let num = slice_to_i32(&more)?;
139 Global::PhysicalMaximum(num)
140 }
141 GlobalItem::UnitExponent => {
142 let num = slice_to_i32(&more)?;
143 Global::UnitExponent(num)
144 }
145 GlobalItem::ReportSize => {
146 let num = slice_to_u32(&more)?;
147 Global::ReportSize(num)
148 }
149 GlobalItem::ReportId => {
150 let num = slice_to_u32(&more)?;
151 Global::ReportId(num)
152 }
153 GlobalItem::ReportCount => {
154 let num = slice_to_u32(&more)?;
155 Global::ReportCount(num)
156 }
157 GlobalItem::Unit => {
158 let num = slice_to_u32(&more)?;
159 let unit = Unit::from_integer(num);
160 Global::Unit(unit)
161 }
162 GlobalItem::Push => Global::Push,
163 GlobalItem::Pop => Global::Pop,
164 GlobalItem::Reserved => Global::Reserved(tag.tag()),
165 };
166 DecodedItem::yes(Item::Global(decoded), iter)
167 }
168 TypeBits::Local => {
169 let item = LocalItem::from(tag.tag());
170 let decoded = match item {
171 LocalItem::Usage => {
172 match slice_to_u16(&more) {
176 Ok(page_id) => match context.usage_page {
177 Some(page) => Local::Usage(Usage::new(page, page_id)),
178
179 None => Local::Usage(Usage::without_page(page_id)),
180 },
181 Err(LengthError::DataTooBig) => {
182 let value = slice_to_u32(&more)?;
183 Local::ExtendedUsage(ExtendedUsage::from_u32(value))
184 }
185 Err(e) => return Err(e),
186 }
187 }
188 LocalItem::UsageMinimum => {
189 let num = slice_to_u32(&more)?;
190 Local::UsageMinimum(num)
191 }
192 LocalItem::UsageMaximum => {
193 let num = slice_to_u32(&more)?;
194 Local::UsageMaximum(num)
195 }
196 LocalItem::DesignatorIndex => {
197 let num = slice_to_u32(&more)?;
198 Local::DesignatorIndex(num)
199 }
200 LocalItem::DesignatorMinimum => {
201 let num = slice_to_u32(&more)?;
202 Local::DesignatorMinimum(num)
203 }
204 LocalItem::DesignatorMaximum => {
205 let num = slice_to_u32(&more)?;
206 Local::DesignatorMaximum(num)
207 }
208 LocalItem::StringIndex => {
209 let num = slice_to_u32(&more)?;
210 Local::StringIndex(num)
211 }
212 LocalItem::StringMinimum => {
213 let num = slice_to_u32(&more)?;
214 Local::StringMinimum(num)
215 }
216 LocalItem::StringMaximum => {
217 let num = slice_to_u32(&more)?;
218 Local::StringMaximum(num)
219 }
220 LocalItem::Delimiter => {
221 let num = slice_to_u8(&more)?;
222 let param = match num {
223 0 => false,
224 1 => true,
225 _ => return Err(LengthError::DataTooBig),
226 };
227 Local::Delimiter(param)
228 }
229 LocalItem::Reserved => Local::Reserved(tag.tag()),
230 };
231 DecodedItem::yes(Item::Local(decoded), iter)
232 }
233 TypeBits::Reserved => {
234 let decoded = Item::Reserved(tag.ty().into_bits());
235 DecodedItem::yes(decoded, iter)
236 }
237 }
238}
239
240struct Recorder<Iter> {
242 inner: Iter,
243 bytes: TinyVec<[u8; 8]>,
244}
245
246impl<Iter> Recorder<Iter> {
247 fn new(iter: Iter) -> Self {
249 Self {
250 inner: iter,
251 bytes: TinyVec::new(),
252 }
253 }
254
255 fn take_bytes(self) -> TinyVec<[u8; 8]> {
257 self.bytes
258 }
259}
260
261impl<Iter> Iterator for Recorder<Iter>
262where
263 Iter: Iterator<Item = u8>,
264{
265 type Item = u8;
266
267 fn next(&mut self) -> Option<Self::Item> {
268 self.inner.next().inspect(|b| {
269 self.bytes.push(*b);
270 })
271 }
272}
273
274#[derive(Clone, Debug, thiserror::Error)]
276pub enum LengthError {
277 #[error("item data too big")]
279 DataTooBig,
280 #[error("missing item data")]
282 ZeroLength,
283 #[error("item data truncated")]
285 Truncated,
286}
287
288fn slice_to_u8(slice: &[u8]) -> Result<u8, LengthError> {
289 match slice.len() {
290 0 => Err(LengthError::ZeroLength),
291 1 => Ok(slice[0]),
292 _ => Err(LengthError::DataTooBig),
293 }
294}
295
296fn slice_to_u16(slice: &[u8]) -> Result<u16, LengthError> {
297 match slice.len() {
298 0 => Err(LengthError::ZeroLength),
299 1 => Ok(slice[0] as u16),
300 2 => {
301 let ar: &[u8; 2] = slice.as_array().unwrap();
302 Ok(u16::from_le_bytes(*ar))
303 }
304 _ => Err(LengthError::DataTooBig),
305 }
306}
307
308fn slice_to_u32(slice: &[u8]) -> Result<u32, LengthError> {
309 match slice.len() {
310 0 => Err(LengthError::ZeroLength),
311 1 => Ok(slice[0] as u32),
312 2 => {
313 let ar: &[u8; 2] = slice.as_array().unwrap();
314 let value = u16::from_le_bytes(*ar);
315 Ok(value as u32)
316 }
317 3 => Err(LengthError::Truncated),
318 4 => {
319 let ar: &[u8; 4] = slice.as_array().unwrap();
320 Ok(u32::from_le_bytes(*ar))
321 }
322 _ => Err(LengthError::DataTooBig),
323 }
324}
325
326fn slice_to_i32(slice: &[u8]) -> Result<i32, LengthError> {
327 match slice.len() {
328 0 => Err(LengthError::ZeroLength),
329 1 => Ok(slice[0] as i8 as i32),
330 2 => {
331 let ar: &[u8; 2] = slice.as_array().unwrap();
332 let value = i16::from_le_bytes(*ar);
333 Ok(value as i32)
334 }
335 3 => Err(LengthError::Truncated),
336 4 => {
337 let ar: &[u8; 4] = slice.as_array().unwrap();
338 Ok(i32::from_le_bytes(*ar))
339 }
340 _ => Err(LengthError::DataTooBig),
341 }
342}
343
344#[cfg(test)]
345mod tests {
346 use super::*;
347
348 #[test]
349 fn _error_traits() {
350 use std::error::Error;
351 use std::fmt::Display;
352 let _err: Box<dyn Error> = Box::new(LengthError::DataTooBig);
353 let _err: Box<dyn Display> = Box::new(LengthError::DataTooBig);
354 assert_eq!(format!("{}", LengthError::Truncated), "item data truncated");
355 }
356
357 #[test]
358 fn test_integer_decoding() {
359 assert_eq!(slice_to_u8(&[0xFF]).unwrap(), 0xFF);
360 slice_to_u8(&[]).unwrap_err();
361 slice_to_u8(&[0xFF, 0xFF]).unwrap_err();
362
363 assert_eq!(slice_to_u16(&[0xFF]).unwrap(), 0xFF);
364 assert_eq!(slice_to_u16(&[0xFF, 0xFF]).unwrap(), 0xFFFF);
365 assert_eq!(slice_to_u16(&[1, 2]).unwrap(), 0x0201);
366 slice_to_u16(&[]).unwrap_err();
367 slice_to_u16(&[0xFF; 3]).unwrap_err();
368 slice_to_u16(&[0xFF; 4]).unwrap_err();
369
370 assert_eq!(slice_to_u32(&[0xFF]).unwrap(), 0xFF);
371 assert_eq!(slice_to_u32(&[0xFF, 0xFF]).unwrap(), 0xFFFF);
372 assert_eq!(slice_to_u32(&[1, 2]).unwrap(), 0x0201);
373 assert_eq!(slice_to_u32(&[0xFF; 4]).unwrap(), 0xFFFFFFFF);
374 assert_eq!(slice_to_u32(&[1, 2, 3, 4]).unwrap(), 0x04030201);
375 slice_to_u32(&[]).unwrap_err();
376 slice_to_u32(&[0xFF; 3]).unwrap_err();
377 slice_to_u32(&[0xFF; 5]).unwrap_err();
378
379 assert_eq!(slice_to_i32(&[0]).unwrap(), 0);
380 assert_eq!(slice_to_i32(&[0, 0]).unwrap(), 0);
381 assert_eq!(slice_to_i32(&[1, 2]).unwrap(), 0x0201);
382 assert_eq!(slice_to_i32(&[0; 4]).unwrap(), 0);
383 assert_eq!(slice_to_i32(&[1, 2, 3, 4]).unwrap(), 0x04030201);
384 assert_eq!(slice_to_i32(&[0xFF]).unwrap(), -1);
385 assert_eq!(slice_to_i32(&[0xFF, 0xFF]).unwrap(), -1);
386 assert_eq!(slice_to_i32(&[0xFF; 4]).unwrap(), -1);
387 slice_to_i32(&[]).unwrap_err();
388 slice_to_i32(&[0xFF; 3]).unwrap_err();
389 slice_to_i32(&[0xFF; 5]).unwrap_err();
390 }
391}