1use hid_types::encoding::{Size, TagTypeSize, TypeBits};
4use hid_types::id::{
5 CollectionType, GlobalItem, InputFlags, IoFlags, LocalItem, MainItem, OutputFeatureFlags, Unit,
6 UnitExponent, UsagePage,
7};
8use hid_types::item::usage::{ExtendedUsage, Usage};
9use hid_types::item::{Global, Item, Local, LongItem, Main};
10use tinyvec::{ArrayVec, TinyVec};
11
12#[derive(Default, Debug, Clone)]
14pub struct DecoderContext {
15 usage_page: Option<UsagePage>,
17 pub(crate) reject_zero_length_values: bool,
22}
23
24pub struct DecodedItem {
26 pub item: Item,
28 pub bytes: TinyVec<[u8; 4]>,
30}
31
32impl DecodedItem {
33 fn new<T>(item: Item, recorder: Recorder<T>) -> Self {
35 Self {
36 item,
37 bytes: recorder.take_bytes(),
38 }
39 }
40}
41
42pub fn decode_one<Iter>(
46 iter: Iter,
47 context: &mut DecoderContext,
48) -> Option<Result<DecodedItem, LengthError>>
49where
50 Iter: Iterator<Item = u8>,
51{
52 let mut iter = Recorder::new(iter);
53
54 let Some(tag) = iter.next() else {
55 return None;
57 };
58 Some(decode_one_inner(iter, context, tag))
59}
60
61fn decode_one_inner<I>(
65 mut iter: Recorder<I>,
66 context: &mut DecoderContext,
67 tag: u8,
68) -> Result<DecodedItem, LengthError>
69where
70 I: Iterator<Item = u8>,
71{
72 let tag = TagTypeSize::from_bits(tag);
73
74 let item_data = match tag.size() {
75 Size::Short(size_bytes) => {
76 ItemData::new(size_bytes, &mut iter, context.reject_zero_length_values)?
77 }
78 Size::Long => {
79 let (Some(size), Some(tag)) = (iter.next(), iter.next()) else {
80 return Err(LengthError::Truncated);
81 };
82 let iter_payload = (&mut iter).take(usize::from(size));
83 let data = iter_payload.collect::<Vec<_>>();
84 if data.len() != size as usize {
85 return Err(LengthError::Truncated);
86 }
87 let item = Item::Long(LongItem { tag, data });
88 return Ok(DecodedItem::new(item, iter));
89 }
90 };
91
92 match tag.ty() {
93 TypeBits::Main => {
94 let item = MainItem::from(tag.tag());
95 let decoded = match item {
96 MainItem::Input => {
97 let data = item_data.to_u32()?;
98 let flags = InputFlags(IoFlags::from(data));
99 Main::Input(flags)
100 }
101 MainItem::Output => {
102 let data = item_data.to_u32()?;
103 let flags = OutputFeatureFlags(IoFlags::from(data));
104 Main::Output(flags)
105 }
106 MainItem::Feature => {
107 let data = item_data.to_u32()?;
108 let flags = OutputFeatureFlags(IoFlags::from(data));
109 Main::Feature(flags)
110 }
111 MainItem::Collection => {
112 let data = item_data.to_u8()?;
113 let coll_type = CollectionType::from_integer(data);
114 Main::Collection(coll_type)
115 }
116 MainItem::EndCollection => {
117 if !item_data.is_empty() {
118 return Err(LengthError::DataTooBig);
119 }
120 Main::EndCollection
121 }
122 MainItem::Reserved => {
123 let data = item_data.to_option_i32()?;
124 Main::Reserved(tag.tag(), data)
125 }
126 };
127 Ok(DecodedItem::new(Item::Main(decoded), iter))
128 }
129 TypeBits::Global => {
130 let item = GlobalItem::from(tag.tag());
131 let decoded = match item {
132 GlobalItem::UsagePage => {
133 let page_number = item_data.to_u16()?;
134 let usage_page = UsagePage::from_integer(page_number);
135 context.usage_page = Some(usage_page);
136 Global::UsagePage(usage_page)
137 }
138 GlobalItem::LogicalMinimum => {
139 let num = item_data.to_i32()?;
140 Global::LogicalMinimum(num)
141 }
142 GlobalItem::LogicalMaximum => {
143 let num = item_data.to_i32()?;
144 Global::LogicalMaximum(num)
145 }
146 GlobalItem::PhysicalMinimum => {
147 let num = item_data.to_i32()?;
148 Global::PhysicalMinimum(num)
149 }
150 GlobalItem::PhysicalMaximum => {
151 let num = item_data.to_i32()?;
152 Global::PhysicalMaximum(num)
153 }
154 GlobalItem::UnitExponent => {
155 let num = item_data.to_i32()?;
159 Global::UnitExponent(UnitExponent(num))
160 }
161 GlobalItem::ReportSize => {
162 let num = item_data.to_u32()?;
163 Global::ReportSize(num)
164 }
165 GlobalItem::ReportId => {
166 let num = item_data.to_u8()?;
167 Global::ReportId(num)
168 }
169 GlobalItem::ReportCount => {
170 let num = item_data.to_u32()?;
171 Global::ReportCount(num)
172 }
173 GlobalItem::Unit => {
174 let num = item_data.to_u32()?;
175 let unit = Unit::from_integer(num);
176 Global::Unit(unit)
177 }
178 GlobalItem::Push => {
179 if !item_data.is_empty() {
180 return Err(LengthError::DataTooBig);
181 }
182 Global::Push
183 }
184 GlobalItem::Pop => {
185 if !item_data.is_empty() {
186 return Err(LengthError::DataTooBig);
187 }
188 Global::Pop
189 }
190 GlobalItem::Reserved => {
191 let data = item_data.to_option_i32()?;
192 Global::Reserved(tag.tag(), data)
193 }
194 };
195 Ok(DecodedItem::new(Item::Global(decoded), iter))
196 }
197 TypeBits::Local => {
198 let item = LocalItem::from(tag.tag());
199 let decoded = match item {
200 LocalItem::Usage => {
201 if item_data.len() == 4 {
205 let value = item_data.to_u32()?;
206 Local::ExtendedUsage(ExtendedUsage::from_u32(value))
207 } else {
208 let usage = item_data.to_u16()?;
209 match context.usage_page {
210 Some(page) => Local::Usage(Usage::new(page, usage)),
211 None => Local::Usage(Usage::without_page(usage)),
212 }
213 }
214 }
215 LocalItem::UsageMinimum => {
216 let num = item_data.to_u32()?;
217 Local::UsageMinimum(num)
218 }
219 LocalItem::UsageMaximum => {
220 let num = item_data.to_u32()?;
221 Local::UsageMaximum(num)
222 }
223 LocalItem::DesignatorIndex => {
224 let num = item_data.to_u32()?;
225 Local::DesignatorIndex(num)
226 }
227 LocalItem::DesignatorMinimum => {
228 let num = item_data.to_u32()?;
229 Local::DesignatorMinimum(num)
230 }
231 LocalItem::DesignatorMaximum => {
232 let num = item_data.to_u32()?;
233 Local::DesignatorMaximum(num)
234 }
235 LocalItem::StringIndex => {
236 let num = item_data.to_u32()?;
237 Local::StringIndex(num)
238 }
239 LocalItem::StringMinimum => {
240 let num = item_data.to_u32()?;
241 Local::StringMinimum(num)
242 }
243 LocalItem::StringMaximum => {
244 let num = item_data.to_u32()?;
245 Local::StringMaximum(num)
246 }
247 LocalItem::Delimiter => {
248 let num = item_data.to_u8()?;
249 let param = match num {
250 0 => false,
251 1 => true,
252 _ => return Err(LengthError::DataTooBig),
253 };
254 Local::Delimiter(param)
255 }
256 LocalItem::Reserved => {
257 let data = item_data.to_option_i32()?;
258 Local::Reserved(tag.tag(), data)
259 }
260 };
261 Ok(DecodedItem::new(Item::Local(decoded), iter))
262 }
263 TypeBits::Reserved => {
264 let data = item_data.to_option_i32()?;
265 let decoded = Item::Reserved(tag.tag(), data);
266 Ok(DecodedItem::new(decoded, iter))
267 }
268 }
269}
270
271struct Recorder<Iter> {
273 inner: Iter,
274 bytes: TinyVec<[u8; 4]>,
275}
276
277impl<Iter> Recorder<Iter> {
278 fn new(iter: Iter) -> Self {
280 Self {
281 inner: iter,
282 bytes: TinyVec::new(),
283 }
284 }
285
286 fn take_bytes(self) -> TinyVec<[u8; 4]> {
288 self.bytes
289 }
290}
291
292impl<Iter> Iterator for Recorder<Iter>
293where
294 Iter: Iterator<Item = u8>,
295{
296 type Item = u8;
297
298 fn next(&mut self) -> Option<Self::Item> {
299 self.inner.next().inspect(|b| {
300 self.bytes.push(*b);
301 })
302 }
303}
304
305#[derive(Clone, Debug, PartialEq, thiserror::Error)]
307pub enum LengthError {
308 #[error("item data too big")]
310 DataTooBig,
311 #[error("missing item data")]
313 ZeroLength,
314 #[error("item data truncated")]
316 Truncated,
317}
318
319struct ItemData {
321 data: ArrayVec<[u8; 4]>,
323 reject_zero_length: bool,
327}
328
329impl ItemData {
330 fn new<I>(size: usize, iter: &mut I, reject_zero_length: bool) -> Result<Self, LengthError>
332 where
333 I: Iterator<Item = u8>,
334 {
335 if size > 4 {
336 panic!("ItemData::new can't be called with size > 4");
337 }
338
339 let mut data = ArrayVec::default();
340 for _ in 0..size {
341 let byte = iter.next().ok_or(LengthError::Truncated)?;
342 data.push(byte);
343 }
344 Ok(Self {
345 data,
346 reject_zero_length,
347 })
348 }
349
350 fn is_empty(&self) -> bool {
351 self.data.is_empty()
352 }
353
354 fn len(&self) -> usize {
355 self.data.len()
356 }
357
358 fn handle_zero<T: Default>(&self) -> Result<T, LengthError> {
359 if self.reject_zero_length {
360 Err(LengthError::ZeroLength)
361 } else {
362 Ok(T::default())
363 }
364 }
365
366 fn to_u8(&self) -> Result<u8, LengthError> {
367 match self.data.len() {
368 0 => self.handle_zero(),
369 1 => Ok(self.data[0]),
370 _ => Err(LengthError::DataTooBig),
371 }
372 }
373
374 fn to_u16(&self) -> Result<u16, LengthError> {
375 match self.data.len() {
376 0 => self.handle_zero(),
377 1 => Ok(self.data[0] as u16),
378 2 => {
379 let ar: &[u8; 2] = self.data.as_array().unwrap();
380 Ok(u16::from_le_bytes(*ar))
381 }
382 _ => Err(LengthError::DataTooBig),
383 }
384 }
385
386 fn to_u32(&self) -> Result<u32, LengthError> {
387 match self.data.len() {
388 0 => self.handle_zero(),
389 1 => Ok(self.data[0] as u32),
390 2 => {
391 let ar: &[u8; 2] = self.data.as_array().unwrap();
392 let value = u16::from_le_bytes(*ar);
393 Ok(value as u32)
394 }
395 3 => Err(LengthError::Truncated),
396 4 => {
397 let ar: &[u8; 4] = self.data.as_array().unwrap();
398 Ok(u32::from_le_bytes(*ar))
399 }
400 _ => Err(LengthError::DataTooBig),
401 }
402 }
403
404 fn to_i32(&self) -> Result<i32, LengthError> {
405 match self.data.len() {
406 0 => self.handle_zero(),
407 1 => Ok(self.data[0] as i8 as i32),
408 2 => {
409 let ar: &[u8; 2] = self.data.as_array().unwrap();
410 let value = i16::from_le_bytes(*ar);
411 Ok(value as i32)
412 }
413 3 => Err(LengthError::Truncated),
414 4 => {
415 let ar: &[u8; 4] = self.data.as_array().unwrap();
416 Ok(i32::from_le_bytes(*ar))
417 }
418 _ => Err(LengthError::DataTooBig),
419 }
420 }
421
422 fn to_option_i32(&self) -> Result<Option<i32>, LengthError> {
423 if self.is_empty() {
424 Ok(None)
425 } else {
426 let value = self.to_i32()?;
427 Ok(Some(value))
428 }
429 }
430}
431
432#[cfg(test)]
433mod tests {
434 use super::*;
435
436 #[test]
437 fn _error_traits() {
438 use std::error::Error;
439 use std::fmt::Display;
440 let _err: Box<dyn Error> = Box::new(LengthError::DataTooBig);
441 let _err: Box<dyn Display> = Box::new(LengthError::DataTooBig);
442 assert_eq!(format!("{}", LengthError::Truncated), "item data truncated");
443 }
444
445 #[test]
446 fn test_integer_decoding() {
447 #[track_caller]
448 fn idata(slice: &[u8]) -> ItemData {
449 ItemData::new(slice.len(), &mut slice.iter().copied(), true)
450 .expect("malformed item data")
451 }
452
453 assert_eq!(idata(&[0xFF]).to_u8().unwrap(), 0xFF);
454 idata(&[]).to_u8().unwrap_err();
455 idata(&[0xFF, 0xFF]).to_u8().unwrap_err();
456
457 #[track_caller]
458 fn test_u16(slice: &[u8], expected: Result<u16, LengthError>) {
459 assert_eq!(idata(slice).to_u16(), expected);
460 }
461
462 test_u16(&[0xFF], Ok(0xFF));
463 test_u16(&[0xFF, 0xFF], Ok(0xFFFF));
464 test_u16(&[1, 2], Ok(0x0201));
465 test_u16(&[], Err(LengthError::ZeroLength));
466 test_u16(&[0xFF; 3], Err(LengthError::DataTooBig));
467 test_u16(&[0xFF; 4], Err(LengthError::DataTooBig));
468
469 #[track_caller]
470 fn test_u32(slice: &[u8], expected: Result<u32, LengthError>) {
471 assert_eq!(idata(slice).to_u32(), expected);
472 }
473
474 test_u32(&[0xFF], Ok(0xFF));
475 test_u32(&[0xFF, 0xFF], Ok(0xFFFF));
476 test_u32(&[1, 2], Ok(0x0201));
477 test_u32(&[0xFF; 4], Ok(0xFFFFFFFF));
478 test_u32(&[1, 2, 3, 4], Ok(0x04030201));
479 test_u32(&[], Err(LengthError::ZeroLength));
480 test_u32(&[0xFF; 3], Err(LengthError::Truncated));
481
482 #[track_caller]
483 fn test_i32(slice: &[u8], expected: Result<i32, LengthError>) {
484 assert_eq!(idata(slice).to_i32(), expected);
485 }
486
487 test_i32(&[0], Ok(0));
488 test_i32(&[0, 0], Ok(0));
489 test_i32(&[0, 0, 0, 0], Ok(0));
490 test_i32(&[1, 2], Ok(0x0201));
491 test_i32(&[0; 4], Ok(0));
492 test_i32(&[1, 2, 3, 4], Ok(0x04030201));
493 test_i32(&[0xFF], Ok(-1));
494 test_i32(&[0xFF, 0xFF], Ok(-1));
495 test_i32(&[0xFF; 4], Ok(-1));
496 test_i32(&[], Err(LengthError::ZeroLength));
497 test_i32(&[0xFF; 3], Err(LengthError::Truncated));
498 }
499}