目标:
usagePage
, usageID
) 整数转换为 Rust 枚举变体,并获取页面名称和特定用法作为字符串以进行调试。usbd_human_interface_device::page
模块提供的枚举。usagePage
或未能在正确的枚举中查找 usageID
。具体:
usbd_human_interface_device::page
中的枚举类型,即 Consumer
、Desktop
、Game
等。
Desktop::SystemPowerDown
是 129
。HIDPage
。HIDPage
变体和关联的特定于页面的变体,例如 Desktop::SystemPowerDown
HIDPage
数字枚举变体指定时,将使用每个枚举类型。也就是说,给定整数元组 (1, 129)
我想返回 (HIDPage::Desktop,
Desktop::SystemPowerDown
)
。挑战:
摘要:
// My HIDPage enum implementation
use num_enum::{TryFromPrimitive};
#[repr(u16)]
#[derive(
Debug,
Copy,
Clone,
Eq,
PartialEq,
Ord,
PartialOrd,
Hash,
TryFromPrimitive,
)]
pub enum HIDPage {
Desktop = 1,
Simulation = 2,
Game = 5,
Keyboard = 7,
Telephony = 0x0b,
Consumer = 0x0c,
}
use usbd_human_interface_device::page::*;
// This enumeration, plus HIDPage, seem overly verbose
#[derive(Debug)]
pub enum HIDEnum {
Desktop(Desktop),
Simulation(Simulation),
Game(Game),
Keyboard(Keyboard),
Telephony(Telephony),
Consumer(Consumer),
}
fn new_usage_from_ints(page:u16 , id: u16) -> Result<String, Box<dyn Error>> {
let knownPage: Option<HIDPage> = HIDPage::try_from(page as u16).ok();
if let Some(knownPage) = knownPage.as_ref() {
let knownId: Option<HIDEnum> = match knownPage {
// Each line requires repeating the type (in different contexts) three times
HIDPage::Desktop => Desktop::try_from(id as u8).ok().map(|v| HIDEnum::Desktop(v)),
HIDPage::Simulation => Simulation::try_from(id as u8).ok().map(|v| HIDEnum::Simulation(v)),
HIDPage::Game => Game::try_from(id as u8).ok().map(|v| HIDEnum::Game(v)),
HIDPage::Keyboard => Keyboard::try_from(id as u8).ok().map(|v| HIDEnum::Keyboard(v)),
HIDPage::Telephony => Telephony::try_from(id as u8).ok().map(|v| HIDEnum::Telephony(v)),
HIDPage::Consumer => Consumer::try_from(id as u16).ok().map(|v| HIDEnum::Consumer(v)),
};
return Ok(format!("nui {:?}/{:?} (0x{:x}/0x{:x})", knownPage, knownId, page, id));
}
return Ok(format!("nui {:?} (0x{:x}/0x{:x})", knownPage, page, id));
}
更好的解决方案可能是仅拥有
HIDEnum
(下面简称为 HID
)并手动实现 TryFrom
或仅拥有其固有功能。
pub enum HID {
Desktop(Desktop),
Simulation(Simulation),
Game(Game),
Keyboard(Keyboard),
Telephony(Telephony),
Consumer(Consumer),
}
impl HID {
pub fn parse(page: u16, id: u16) -> Result<HID, Box<dyn Error>> {
let out = match page {
1 => HID::Desktop(Desktop::try_from(u8::try_from(id)?)?),
2 => HID::Simulation(Simulation::try_from(u8::try_from(id)?)?),
5 => HID::Game(Game::try_from(u8::try_from(id)?)?),
7 => HID::Keyboard(Keyboard::try_from(u8::try_from(id)?)?),
0x0b => HID::Telephony(Telephony::try_from(u8::try_from(id)?)?),
0x0c => HID::Consumer(Consumer::try_from(id)?),
_ => Err(UnknownPageError)?,
};
Ok(out)
}
}
但是如果您想让事情更具声明性,您可以使用单独的枚举作为页面 ID 并将其映射到
HID
:
#[repr(u16)]
#[derive(
Debug,
Copy,
Clone,
Eq,
PartialEq,
Ord,
PartialOrd,
Hash,
TryFromPrimitive,
)]
pub enum PageId {
Desktop = 1,
Simulation = 2,
Game = 5,
Keyboard = 7,
Telephony = 0x0b,
Consumer = 0x0c,
}
impl HID {
pub fn parse2(page: u16, id: u16) -> Result<HID, Box<dyn Error>> {
let page = PageId::try_from(page)?;
let out = match page {
PageId::Desktop => HID::Desktop(Desktop::try_from(u8::try_from(id)?)?),
PageId::Simulation => HID::Simulation(Simulation::try_from(u8::try_from(id)?)?),
PageId::Game => HID::Game(Game::try_from(u8::try_from(id)?)?),
PageId::Keyboard => HID::Keyboard(Keyboard::try_from(u8::try_from(id)?)?),
PageId::Telephony => HID::Telephony(Telephony::try_from(u8::try_from(id)?)?),
PageId::Consumer => HID::Consumer(Consumer::try_from(id)?),
};
Ok(out)
}
}