keyboard_codes/types/
keyboard_input.rs1use crate::error::KeyParseError;
2use crate::mapping::standard::parse_key_ignore_case;
3use crate::parser::{normalize_key_name, parse_modifier_with_aliases};
4use crate::types::{Key, KeyCodeMapper, Modifier, Platform};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub enum KeyboardInput {
10 Key(Key),
12 Modifier(Modifier),
14}
15
16impl KeyboardInput {
17 pub fn as_str(&self) -> &'static str {
19 match self {
20 KeyboardInput::Key(key) => key.as_str(),
21 KeyboardInput::Modifier(modifier) => modifier.as_str(),
22 }
23 }
24
25 pub fn to_code(&self, platform: Platform) -> usize {
27 match self {
28 KeyboardInput::Key(key) => KeyCodeMapper::to_code(key, platform),
29 KeyboardInput::Modifier(modifier) => KeyCodeMapper::to_code(modifier, platform),
30 }
31 }
32
33 pub fn from_code(code: usize, platform: Platform) -> Option<Self> {
35 Key::from_code(code, platform)
37 .map(KeyboardInput::Key)
38 .or_else(|| Modifier::from_code(code, platform).map(KeyboardInput::Modifier))
39 }
40
41 pub fn is_key(&self) -> bool {
43 matches!(self, KeyboardInput::Key(_))
44 }
45
46 pub fn is_modifier(&self) -> bool {
48 matches!(self, KeyboardInput::Modifier(_))
49 }
50
51 pub fn as_key(&self) -> Option<Key> {
53 match self {
54 KeyboardInput::Key(key) => Some(*key),
55 _ => None,
56 }
57 }
58
59 pub fn as_modifier(&self) -> Option<Modifier> {
61 match self {
62 KeyboardInput::Modifier(modifier) => Some(*modifier),
63 _ => None,
64 }
65 }
66
67 pub fn parse_with_aliases(input: &str) -> Result<Self, KeyParseError> {
69 if input.is_empty() {
70 return Err(KeyParseError::UnknownKey("empty string".to_string()));
71 }
72
73 if let Ok(modifier) = parse_modifier_with_aliases(input) {
75 return Ok(KeyboardInput::Modifier(modifier));
76 }
77
78 let normalized_key = normalize_key_name(input);
80 if let Ok(key) = parse_key_ignore_case(normalized_key) {
81 return Ok(KeyboardInput::Key(key));
82 }
83
84 Err(KeyParseError::UnknownKey(input.to_string()))
85 }
86}
87
88impl std::fmt::Display for KeyboardInput {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 write!(f, "{}", self.as_str())
91 }
92}
93
94impl std::str::FromStr for KeyboardInput {
95 type Err = KeyParseError;
96
97 fn from_str(s: &str) -> Result<Self, Self::Err> {
98 if let Ok(key) = s.parse::<Key>() {
100 return Ok(KeyboardInput::Key(key));
101 }
102
103 if let Ok(modifier) = s.parse::<Modifier>() {
104 return Ok(KeyboardInput::Modifier(modifier));
105 }
106
107 Self::parse_with_aliases(s)
109 }
110}
111
112impl KeyCodeMapper for KeyboardInput {
114 fn to_code(&self, platform: Platform) -> usize {
115 self.to_code(platform)
116 }
117
118 fn from_code(code: usize, platform: Platform) -> Option<Self> {
119 Self::from_code(code, platform)
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 #[test]
128 fn test_keyboard_input_creation() {
129 let key_input = KeyboardInput::Key(Key::A);
130 let modifier_input = KeyboardInput::Modifier(Modifier::Control);
131
132 assert!(key_input.is_key());
133 assert!(modifier_input.is_modifier());
134 assert_eq!(key_input.as_key(), Some(Key::A));
135 assert_eq!(modifier_input.as_modifier(), Some(Modifier::Control));
136 }
137
138 #[test]
139 fn test_keyboard_input_from_str() {
140 assert_eq!(
141 "A".parse::<KeyboardInput>().unwrap(),
142 KeyboardInput::Key(Key::A)
143 );
144 assert_eq!(
145 "Control".parse::<KeyboardInput>().unwrap(),
146 KeyboardInput::Modifier(Modifier::Control)
147 );
148 assert_eq!(
149 "ctrl".parse::<KeyboardInput>().unwrap(),
150 KeyboardInput::Modifier(Modifier::Control)
151 );
152 assert_eq!(
153 "esc".parse::<KeyboardInput>().unwrap(),
154 KeyboardInput::Key(Key::Escape)
155 );
156 }
157
158 #[test]
159 fn test_keyboard_input_to_code() {
160 let key_input = KeyboardInput::Key(Key::Enter);
161 let modifier_input = KeyboardInput::Modifier(Modifier::Shift);
162
163 assert_eq!(key_input.to_code(Platform::Windows), 0x0D);
164 assert_eq!(modifier_input.to_code(Platform::Windows), 0x10);
165 }
166
167 #[test]
168 fn test_keyboard_input_from_code() {
169 assert_eq!(
170 KeyboardInput::from_code(0x41, Platform::Windows),
171 Some(KeyboardInput::Key(Key::A))
172 );
173 assert_eq!(
174 KeyboardInput::from_code(0x10, Platform::Windows),
175 Some(KeyboardInput::Modifier(Modifier::Shift))
176 );
177 }
178
179 #[test]
180 fn test_keyboard_input_display() {
181 assert_eq!(KeyboardInput::Key(Key::Enter).to_string(), "Enter");
182 assert_eq!(
183 KeyboardInput::Modifier(Modifier::Control).to_string(),
184 "Control"
185 );
186 }
187}