diff --git a/src/attribute_set.rs b/src/attribute_set.rs index 06e2d24..52afc98 100644 --- a/src/attribute_set.rs +++ b/src/attribute_set.rs @@ -182,6 +182,20 @@ macro_rules! evdev_enum { impl $t { $($(#[$attr])* pub const $c: Self = Self($val);)* } + impl std::str::FromStr for $t { + type Err = crate::EnumParseError; + + fn from_str(s: &str) -> Result { + let map: &[(&'static str, $t)] = &[ + $((stringify!($c), Self::$c),)* + ]; + + match map.iter().find(|e| e.0 == s) { + Some(e) => Ok(e.1), + None => Err(crate::EnumParseError(())), + } + } + } impl std::fmt::Debug for $t { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match *self { diff --git a/src/lib.rs b/src/lib.rs index c329cc6..c8bcafd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -290,3 +290,6 @@ pub(crate) fn nix_err(err: nix::Error) -> io::Error { pub(crate) unsafe fn cast_to_bytes(mem: &T) -> &[u8] { std::slice::from_raw_parts(mem as *const T as *const u8, std::mem::size_of_val(mem)) } + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct EnumParseError(()); diff --git a/src/scancodes.rs b/src/scancodes.rs index 02e2bc3..f6e4fea 100644 --- a/src/scancodes.rs +++ b/src/scancodes.rs @@ -555,3 +555,11 @@ evdev_enum!( BTN_TRIGGER_HAPPY39 = 0x2e6, BTN_TRIGGER_HAPPY40 = 0x2e7, ); + +#[test] +fn from_str() { + use std::str::FromStr; + + assert_eq!(Key::from_str("KEY_A"), Ok(Key::KEY_A)); + assert!(Key::from_str("KEY_FOOBAR").is_err()); +}