use bitfield_struct::bitfield;
use num_enum::{IntoPrimitive, TryFromPrimitive};
use crate::Ident;
#[bitfield(u32, debug = false)]
#[derive(PartialEq)]
pub struct IoFlags {
#[bits(1)]
data_or_constant: bool,
#[bits(1)]
array_or_variable: bool,
#[bits(1)]
absolute_or_relative: bool,
#[bits(1)]
wrap: bool,
#[bits(1)]
non_linear: bool,
#[bits(1)]
no_preferred: bool,
#[bits(1)]
null_state: bool,
#[bits(1)]
volatile: bool,
#[bits(1)]
bitfield_or_buffered: bool,
#[bits(23)]
reserved: u32,
}
impl IoFlags {
pub const fn data() -> Self {
Self::new()
}
pub const fn constant() -> Self {
Self::new().with_data_or_constant(true)
}
pub const fn variable(self) -> Self {
self.with_array_or_variable(true)
}
pub const fn relative(self) -> Self {
self.with_absolute_or_relative(true)
}
}
pub mod ioflags {
use super::IoFlags;
pub const DATA_VARIABLE_ABSOLUTE: IoFlags = IoFlags::data().variable();
pub const CONSTANT: IoFlags = IoFlags::constant();
pub const ARRAY: IoFlags = IoFlags::data();
}
#[derive(Clone, Copy, PartialEq)]
pub struct InputFlags(pub IoFlags);
#[derive(Clone, Copy, PartialEq)]
pub struct OutputFeatureFlags(pub IoFlags);
#[expect(missing_docs)]
#[derive(Clone, Copy, Debug, PartialEq, TryFromPrimitive, IntoPrimitive)]
#[repr(u8)]
pub enum KnownCollectionType {
Physical = 0,
Application = 1,
Logical = 2,
Report = 3,
NamedArray = 4,
UsageSwitch = 5,
UsageModifier = 6,
}
pub type CollectionType = Ident<KnownCollectionType, u8>;
#[expect(missing_docs)]
#[derive(Clone, Copy, Debug, PartialEq, TryFromPrimitive)]
#[repr(u32)]
#[non_exhaustive]
pub enum KnownUnit {
Centimeter = 0x11,
Radian = 0x12,
Inch = 0x13,
Degree = 0x14,
}
pub type Unit = Ident<KnownUnit, u32>;
#[cfg(feature = "std")]
mod std_impls {
use super::*;
use std::fmt::{self, Debug};
fn debug_flags(is_input: bool, flags: IoFlags, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if flags.data_or_constant() {
f.write_str("Constant ")?;
} else {
f.write_str("Data ")?;
}
if flags.array_or_variable() {
f.write_str("Variable ")?;
} else {
f.write_str("Array ")?;
}
if flags.absolute_or_relative() {
f.write_str("Relative ")?;
} else {
f.write_str("Absolute ")?;
}
if flags.wrap() {
f.write_str("Wrap ")?;
} else {
f.write_str("No-Wrap ")?;
}
if flags.non_linear() {
f.write_str("Non-Linear ")?;
} else {
f.write_str("Linear ")?;
}
if flags.no_preferred() {
f.write_str("No-Preferred ")?;
} else {
f.write_str("Preferred-State ")?;
}
if flags.null_state() {
f.write_str("Null-State ")?
} else {
f.write_str("No-Null-Position ")?;
}
if flags.volatile() {
f.write_str("Volatile ")?;
} else {
if !is_input {
f.write_str("Non-Volatile ")?;
}
}
if flags.bitfield_or_buffered() {
f.write_str("Buffered-Bytes")?;
} else {
f.write_str("Bit-Field")?;
}
Ok(())
}
impl Debug for InputFlags {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
debug_flags(true, self.0, f)
}
}
impl Debug for OutputFeatureFlags {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
debug_flags(false, self.0, f)
}
}
}