1use crate::id::CollectionType;
7use crate::id::usage::UsagePage;
8use crate::id::{InputFlags, OutputFeatureFlags};
9use crate::id::{Unit, UnitExponent};
10use crate::item::usage::{ExtendedUsage, Usage};
11
12pub mod usage;
13
14#[derive(Clone, PartialEq)]
16#[cfg_attr(feature = "std", derive(Debug))]
17pub enum Item {
18 Long(LongItem),
24 Main(Main),
29 Global(Global),
31 Local(Local),
33 Reserved(u8, Option<i32>),
37}
38
39impl Item {
40 #[cfg(feature = "std")]
41 pub fn type_note(&self) -> &'static str {
43 match self {
44 Item::Long(_) => "[long]",
45 Item::Main(_) => "[main]",
46 Item::Global(_) => "[global]",
47 Item::Local(_) => "[local]",
48 Item::Reserved(_, _) => "[reserved]",
49 }
50 }
51}
52
53#[derive(Clone, PartialEq)]
58#[cfg_attr(feature = "std", derive(Debug))]
59pub enum Main {
60 Input(InputFlags),
62 Output(OutputFeatureFlags),
64 Feature(OutputFeatureFlags),
66 Collection(CollectionType),
68 EndCollection,
70 Reserved(u8, Option<i32>),
72}
73
74#[derive(Clone, PartialEq)]
76#[cfg_attr(feature = "std", derive(Debug))]
77pub enum Global {
78 UsagePage(UsagePage),
83 LogicalMinimum(i32),
85 LogicalMaximum(i32),
87 PhysicalMinimum(i32),
89 PhysicalMaximum(i32),
91 UnitExponent(UnitExponent),
96 Unit(Unit),
98 ReportSize(u32),
100 ReportId(u8),
102 ReportCount(u32),
104 Push,
106 Pop,
108 Reserved(u8, Option<i32>),
110}
111
112#[derive(Clone, PartialEq)]
114#[cfg_attr(feature = "std", derive(Debug))]
115pub enum Local {
116 Usage(Usage),
118 ExtendedUsage(ExtendedUsage),
120 UsageMinimum(u32),
122 UsageMaximum(u32),
124 DesignatorIndex(u32),
126 DesignatorMinimum(u32),
128 DesignatorMaximum(u32),
130 StringIndex(u32),
132 StringMinimum(u32),
134 StringMaximum(u32),
136 Delimiter(bool),
138 Reserved(u8, Option<i32>),
140}
141
142#[derive(Clone, PartialEq)]
148#[cfg_attr(feature = "std", derive(Debug))]
149#[expect(missing_docs)]
150pub struct LongItem {
151 pub tag: u8,
152 #[cfg(feature = "std")]
153 pub data: std::vec::Vec<u8>,
154}
155
156#[cfg(feature = "std")]
157mod std_impls {
158 use std::fmt::{self, Display};
159
160 use super::*;
161
162 impl Display for Item {
163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164 match self {
165 Item::Long(item) => {
166 write!(f, "tag {:#04x} [{} bytes]", item.tag, item.data.len())
167 }
168 Item::Main(item) => {
169 write!(f, "{item}")
170 }
171 Item::Global(item) => {
172 write!(f, "{item}")
173 }
174 Item::Local(item) => write!(f, "{item}"),
175 Item::Reserved(ty, _) => write!(f, "reserved type {ty}"),
176 }
177 }
178 }
179
180 impl Display for Main {
181 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182 match self {
183 Main::Input(flags) => {
184 write!(f, "Input: {flags:?}")
185 }
186 Main::Output(flags) => {
187 write!(f, "Output: {flags:?}")
188 }
189 Main::Feature(flags) => {
190 write!(f, "Feature: {flags:?}")
191 }
192 Main::Collection(coll) => {
193 write!(f, "Collection: {coll:?}")
194 }
195 Main::EndCollection => {
196 write!(f, "EndCollection")
197 }
198 Main::Reserved(tag, data) => {
199 write!(f, "Reserved tag {tag:#04X}")?;
200 if let Some(data) = &data {
201 write!(f, "with data {data:#04x}")?;
202 }
203 Ok(())
204 }
205 }
206 }
207 }
208
209 impl Display for Global {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 match self {
212 Global::UsagePage(page) => {
213 write!(f, "Usage Page: {page:?}")
214 }
215 Global::LogicalMinimum(value) => write!(f, "Logical Minimum: {value}"),
216 Global::LogicalMaximum(value) => write!(f, "Logical Maximum: {value}"),
217 Global::PhysicalMinimum(value) => write!(f, "Physical Minimum: {value}"),
218 Global::PhysicalMaximum(value) => write!(f, "Physical Maximum: {value}"),
219 Global::UnitExponent(value) => write!(f, "Unit Exponent: {value}"),
220 Global::Unit(unit) => write!(f, "Unit: {unit:?}"),
221 Global::Push => write!(f, "Push"),
222 Global::Pop => write!(f, "Pop"),
223 Global::Reserved(tag, data) => {
224 write!(f, "Reserved tag {tag:#04X}")?;
225 if let Some(data) = &data {
226 write!(f, "with data {data:#04x}")?;
227 }
228 Ok(())
229 }
230 Global::ReportSize(value) => write!(f, "Report Size: {value}"),
231 Global::ReportId(value) => write!(f, "Report ID: {value}"),
232 Global::ReportCount(value) => write!(f, "Report Count: {value}"),
233 }
234 }
235 }
236
237 impl Display for Local {
238 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
239 match self {
240 Local::Usage(usage) => {
241 write!(f, "Usage: {usage}")
242 }
243 Local::ExtendedUsage(extended_usage) => {
244 write!(f, "Extended Usage: {extended_usage:?}")
245 }
246 Local::UsageMinimum(value) => {
247 write!(f, "Usage Minimum: {value}")
248 }
249 Local::UsageMaximum(value) => {
250 write!(f, "Usage Maximum: {value}")
251 }
252 Local::DesignatorIndex(value) => write!(f, "Designator Index: {value}"),
253 Local::DesignatorMinimum(value) => write!(f, "Designator Minimum: {value}"),
254 Local::DesignatorMaximum(value) => write!(f, "Designator Maximum: {value}"),
255 Local::StringIndex(value) => write!(f, "String Index: {value}"),
256 Local::StringMinimum(value) => write!(f, "String Minimum: {value}"),
257 Local::StringMaximum(value) => write!(f, "String Maximum: {value}"),
258 Local::Delimiter(value) => write!(f, "Delimiter: {value}"),
259 Local::Reserved(tag, data) => {
260 write!(f, "Reserved tag {tag:#04X}")?;
261 if let Some(data) = &data {
262 write!(f, "with data {data:#04x}")?;
263 }
264 Ok(())
265 }
266 }
267 }
268 }
269}