1use crate::error::KeyParseError;
2use crate::types::{Key, Modifier, Platform};
3
4pub const STANDARD_KEY_MAPPINGS: &[(&str, Key, usize, usize, usize)] = &[
7 ("Escape", Key::Escape, 0x1B, 1, 53),
8 ("Enter", Key::Enter, 0x0D, 28, 36),
9 ("Tab", Key::Tab, 0x09, 15, 48),
10 ("Backspace", Key::Backspace, 0x08, 14, 51),
11 ("Space", Key::Space, 0x20, 57, 49),
12 ("Insert", Key::Insert, 0x2D, 110, 114),
13 ("Delete", Key::Delete, 0x2E, 111, 117),
14 ("Home", Key::Home, 0x24, 102, 115),
15 ("End", Key::End, 0x23, 107, 119),
16 ("PageUp", Key::PageUp, 0x21, 104, 116),
17 ("PageDown", Key::PageDown, 0x22, 109, 121),
18 ("ArrowLeft", Key::ArrowLeft, 0x25, 105, 123),
19 ("ArrowUp", Key::ArrowUp, 0x26, 103, 126),
20 ("ArrowRight", Key::ArrowRight, 0x27, 106, 124),
21 ("ArrowDown", Key::ArrowDown, 0x28, 108, 125),
22 ("A", Key::A, 0x41, 30, 0),
23 ("B", Key::B, 0x42, 48, 11),
24 ("C", Key::C, 0x43, 46, 8),
25 ("D", Key::D, 0x44, 32, 2),
26 ("E", Key::E, 0x45, 18, 14),
27 ("F", Key::F, 0x46, 33, 3),
28 ("G", Key::G, 0x47, 34, 5),
29 ("H", Key::H, 0x48, 35, 4),
30 ("I", Key::I, 0x49, 23, 34),
31 ("J", Key::J, 0x4A, 36, 38),
32 ("K", Key::K, 0x4B, 37, 40),
33 ("L", Key::L, 0x4C, 38, 37),
34 ("M", Key::M, 0x4D, 50, 46),
35 ("N", Key::N, 0x4E, 49, 45),
36 ("O", Key::O, 0x4F, 24, 31),
37 ("P", Key::P, 0x50, 25, 35),
38 ("Q", Key::Q, 0x51, 16, 12),
39 ("R", Key::R, 0x52, 19, 15),
40 ("S", Key::S, 0x53, 31, 1),
41 ("T", Key::T, 0x54, 20, 17),
42 ("U", Key::U, 0x55, 22, 32),
43 ("V", Key::V, 0x56, 47, 9),
44 ("W", Key::W, 0x57, 17, 13),
45 ("X", Key::X, 0x58, 45, 7),
46 ("Y", Key::Y, 0x59, 21, 16),
47 ("Z", Key::Z, 0x5A, 44, 6),
48 ("D0", Key::D0, 0x30, 11, 29),
49 ("D1", Key::D1, 0x31, 2, 18),
50 ("D2", Key::D2, 0x32, 3, 19),
51 ("D3", Key::D3, 0x33, 4, 20),
52 ("D4", Key::D4, 0x34, 5, 21),
53 ("D5", Key::D5, 0x35, 6, 23),
54 ("D6", Key::D6, 0x36, 7, 22),
55 ("D7", Key::D7, 0x37, 8, 26),
56 ("D8", Key::D8, 0x38, 9, 28),
57 ("D9", Key::D9, 0x39, 10, 25),
58 ("Num0", Key::Num0, 0x60, 82, 82),
59 ("Num1", Key::Num1, 0x61, 79, 83),
60 ("Num2", Key::Num2, 0x62, 80, 84),
61 ("Num3", Key::Num3, 0x63, 81, 85),
62 ("Num4", Key::Num4, 0x64, 75, 86),
63 ("Num5", Key::Num5, 0x65, 76, 87),
64 ("Num6", Key::Num6, 0x66, 77, 88),
65 ("Num7", Key::Num7, 0x67, 71, 89),
66 ("Num8", Key::Num8, 0x68, 72, 91),
67 ("Num9", Key::Num9, 0x69, 73, 92),
68 ("NumMultiply", Key::NumMultiply, 0x6A, 55, 67),
69 ("NumAdd", Key::NumAdd, 0x6B, 78, 69),
70 ("NumSubtract", Key::NumSubtract, 0x6D, 74, 78),
71 ("NumDivide", Key::NumDivide, 0x6F, 53, 75),
72 ("NumDecimal", Key::NumDecimal, 0x6E, 83, 65),
73 ("F1", Key::F1, 0x70, 59, 122),
74 ("F2", Key::F2, 0x71, 60, 120),
75 ("F3", Key::F3, 0x72, 61, 99),
76 ("F4", Key::F4, 0x73, 62, 118),
77 ("F5", Key::F5, 0x74, 63, 96),
78 ("F6", Key::F6, 0x75, 64, 97),
79 ("F7", Key::F7, 0x76, 65, 98),
80 ("F8", Key::F8, 0x77, 66, 100),
81 ("F9", Key::F9, 0x78, 67, 101),
82 ("F10", Key::F10, 0x79, 68, 109),
83 ("F11", Key::F11, 0x7A, 87, 103),
84 ("F12", Key::F12, 0x7B, 88, 111),
85 ("F13", Key::F13, 0x7C, 183, 104),
86 ("F14", Key::F14, 0x7D, 184, 105),
87 ("F15", Key::F15, 0x7E, 185, 106),
88 ("F16", Key::F16, 0x7F, 186, 107),
89 ("F17", Key::F17, 0x80, 187, 108),
90 ("F18", Key::F18, 0x81, 188, 110),
91 ("F19", Key::F19, 0x82, 189, 112),
92 ("F20", Key::F20, 0x83, 190, 113),
93 ("F21", Key::F21, 0x84, 191, 102),
94 ("F22", Key::F22, 0x85, 192, 121),
95 ("F23", Key::F23, 0x86, 193, 122),
96 ("F24", Key::F24, 0x87, 194, 123),
97 ("CapsLock", Key::CapsLock, 0x14, 58, 57),
98 ("NumLock", Key::NumLock, 0x90, 69, 71),
99 ("ScrollLock", Key::ScrollLock, 0x91, 70, 72),
100 ("Pause", Key::Pause, 0x13, 119, 117),
101 ("Apps", Key::Apps, 0x5D, 135, 110),
102 ("Sleep", Key::Sleep, 0x5F, 142, 142),
103 ("MediaPlayPause", Key::MediaPlayPause, 0xB3, 164, 163),
104 ("MediaStop", Key::MediaStop, 0xB2, 165, 165),
105 ("MediaNext", Key::MediaNext, 0xB0, 163, 171),
106 ("MediaPrevious", Key::MediaPrevious, 0xB1, 166, 172),
107 ("VolumeUp", Key::VolumeUp, 0xAF, 123, 126),
108 ("VolumeDown", Key::VolumeDown, 0xAE, 122, 125),
109 ("VolumeMute", Key::VolumeMute, 0xAD, 121, 127),
110 ("BrowserBack", Key::BrowserBack, 0xA6, 166, 178),
111 ("BrowserForward", Key::BrowserForward, 0xA7, 167, 179),
112 ("BrowserRefresh", Key::BrowserRefresh, 0xA8, 168, 177),
113 ("BrowserHome", Key::BrowserHome, 0xAC, 178, 174),
114];
115
116pub const STANDARD_MODIFIER_MAPPINGS: &[(&str, Modifier, usize, usize, usize)] = &[
118 ("Alt", Modifier::Alt, 0x12, 56, 61),
119 ("Control", Modifier::Control, 0x11, 29, 59),
120 ("Shift", Modifier::Shift, 0x10, 42, 60),
121 ("Meta", Modifier::Meta, 0x5B, 125, 55),
122 ("LeftAlt", Modifier::LeftAlt, 0xA4, 56, 61),
123 ("RightAlt", Modifier::RightAlt, 0xA5, 100, 61),
124 ("LeftControl", Modifier::LeftControl, 0xA2, 29, 59),
125 ("RightControl", Modifier::RightControl, 0xA3, 97, 59),
126 ("LeftShift", Modifier::LeftShift, 0xA0, 42, 60),
127 ("RightShift", Modifier::RightShift, 0xA1, 54, 60),
128 ("LeftMeta", Modifier::LeftMeta, 0x5B, 125, 55),
129 ("RightMeta", Modifier::RightMeta, 0x5C, 126, 55),
130];
131
132pub fn parse_key_from_str(s: &str) -> Result<Key, KeyParseError> {
134 STANDARD_KEY_MAPPINGS
135 .iter()
136 .find(|(name, _, _, _, _)| *name == s)
137 .map(|(_, key, _, _, _)| *key)
138 .ok_or_else(|| KeyParseError::UnknownKey(s.to_string()))
139}
140
141pub fn parse_modifier_from_str(s: &str) -> Result<Modifier, KeyParseError> {
143 STANDARD_MODIFIER_MAPPINGS
144 .iter()
145 .find(|(name, _, _, _, _)| *name == s)
146 .map(|(_, modifier, _, _, _)| *modifier)
147 .ok_or_else(|| KeyParseError::UnknownModifier(s.to_string()))
148}
149
150pub fn parse_key_ignore_case(s: &str) -> Result<Key, KeyParseError> {
152 STANDARD_KEY_MAPPINGS
153 .iter()
154 .find(|(name, _, _, _, _)| name.eq_ignore_ascii_case(s))
155 .map(|(_, key, _, _, _)| *key)
156 .ok_or_else(|| KeyParseError::UnknownKey(s.to_string()))
157}
158
159pub fn parse_modifier_ignore_case(s: &str) -> Result<Modifier, KeyParseError> {
161 STANDARD_MODIFIER_MAPPINGS
162 .iter()
163 .find(|(name, _, _, _, _)| name.eq_ignore_ascii_case(s))
164 .map(|(_, modifier, _, _, _)| *modifier)
165 .ok_or_else(|| KeyParseError::UnknownModifier(s.to_string()))
166}
167
168pub fn key_to_code(key: Key, platform: Platform) -> usize {
170 STANDARD_KEY_MAPPINGS
171 .iter()
172 .find(|(_, k, _, _, _)| k == &key)
173 .map(|(_, _, win, linux, mac)| match platform {
174 Platform::Windows => *win,
175 Platform::Linux => *linux,
176 Platform::MacOS => *mac,
177 })
178 .unwrap_or_else(|| panic!("Unsupported key in standard mapping: {:?}", key))
179}
180
181pub fn modifier_to_code(modifier: Modifier, platform: Platform) -> usize {
183 STANDARD_MODIFIER_MAPPINGS
184 .iter()
185 .find(|(_, m, _, _, _)| m == &modifier)
186 .map(|(_, _, win, linux, mac)| match platform {
187 Platform::Windows => *win,
188 Platform::Linux => *linux,
189 Platform::MacOS => *mac,
190 })
191 .unwrap_or_else(|| panic!("Unsupported modifier in standard mapping: {:?}", modifier))
192}
193
194pub fn key_from_code(code: usize, platform: Platform) -> Option<Key> {
196 STANDARD_KEY_MAPPINGS
197 .iter()
198 .find(|(_, _, win, linux, mac)| match platform {
199 Platform::Windows => *win == code,
200 Platform::Linux => *linux == code,
201 Platform::MacOS => *mac == code,
202 })
203 .map(|(_, key, _, _, _)| *key)
204}
205
206pub fn modifier_from_code(code: usize, platform: Platform) -> Option<Modifier> {
208 STANDARD_MODIFIER_MAPPINGS
209 .iter()
210 .find(|(_, _, win, linux, mac)| match platform {
211 Platform::Windows => *win == code,
212 Platform::Linux => *linux == code,
213 Platform::MacOS => *mac == code,
214 })
215 .map(|(_, modifier, _, _, _)| *modifier)
216}
217
218impl crate::types::KeyCodeMapper for Key {
220 fn to_code(&self, platform: Platform) -> usize {
221 key_to_code(*self, platform)
222 }
223
224 fn from_code(code: usize, platform: Platform) -> Option<Self> {
225 key_from_code(code, platform)
226 }
227}
228
229impl crate::types::KeyCodeMapper for Modifier {
231 fn to_code(&self, platform: Platform) -> usize {
232 modifier_to_code(*self, platform)
233 }
234
235 fn from_code(code: usize, platform: Platform) -> Option<Self> {
236 modifier_from_code(code, platform)
237 }
238}
239
240#[cfg(test)]
241mod tests {
242 use super::*;
243
244 #[test]
245 fn test_parse_key_from_str() {
246 assert_eq!(parse_key_from_str("Escape").unwrap(), Key::Escape);
247 assert_eq!(parse_key_from_str("A").unwrap(), Key::A);
248 assert!(parse_key_from_str("UnknownKey").is_err());
249 }
250
251 #[test]
252 fn test_parse_modifier_from_str() {
253 assert_eq!(parse_modifier_from_str("Shift").unwrap(), Modifier::Shift);
254 assert_eq!(
255 parse_modifier_from_str("Control").unwrap(),
256 Modifier::Control
257 );
258 assert!(parse_modifier_from_str("UnknownModifier").is_err());
259 }
260
261 #[test]
262 fn test_parse_key_ignore_case() {
263 assert_eq!(parse_key_ignore_case("escape").unwrap(), Key::Escape);
264 assert_eq!(parse_key_ignore_case("ESCAPE").unwrap(), Key::Escape);
265 assert_eq!(parse_key_ignore_case("Escape").unwrap(), Key::Escape);
266 assert_eq!(parse_key_ignore_case("a").unwrap(), Key::A);
267 assert_eq!(parse_key_ignore_case("A").unwrap(), Key::A);
268 }
269
270 #[test]
271 fn test_parse_modifier_ignore_case() {
272 assert_eq!(
273 parse_modifier_ignore_case("shift").unwrap(),
274 Modifier::Shift
275 );
276 assert_eq!(
277 parse_modifier_ignore_case("SHIFT").unwrap(),
278 Modifier::Shift
279 );
280 assert_eq!(
281 parse_modifier_ignore_case("Shift").unwrap(),
282 Modifier::Shift
283 );
284 assert_eq!(
285 parse_modifier_ignore_case("control").unwrap(),
286 Modifier::Control
287 );
288 assert_eq!(
289 parse_modifier_ignore_case("CONTROL").unwrap(),
290 Modifier::Control
291 );
292 }
293
294 #[test]
295 fn test_key_to_code() {
296 assert_eq!(key_to_code(Key::Enter, Platform::Windows), 0x0D);
297 assert_eq!(key_to_code(Key::Enter, Platform::Linux), 28);
298 assert_eq!(key_to_code(Key::Enter, Platform::MacOS), 36);
299 }
300
301 #[test]
302 fn test_key_from_code() {
303 assert_eq!(key_from_code(0x1B, Platform::Windows), Some(Key::Escape));
304 assert_eq!(key_from_code(1, Platform::Linux), Some(Key::Escape));
305 assert_eq!(key_from_code(53, Platform::MacOS), Some(Key::Escape));
306 }
307
308 #[test]
309 fn test_key_code_mapper_impl() {
310 use crate::types::KeyCodeMapper;
311
312 let key = Key::Enter;
313 assert_eq!(key.to_code(Platform::Windows), 0x0D);
314 assert_eq!(Key::from_code(0x0D, Platform::Windows), Some(Key::Enter));
315 }
316}