pub const NAMED_KEYS: &[(&str, u32)] = &[
("a", 19), ("b", 20), ("c", 21), ("d", 22), ("e", 23), ("f", 24), ("g", 25), ("h", 26), ("i", 27), ("j", 28), ("k", 29), ("l", 30), ("m", 31), ("n", 32), ("o", 33), ("p", 34), ("q", 35), ("r", 36), ("s", 37), ("t", 38), ("u", 39), ("v", 40), ("w", 41), ("x", 42), ("y", 43), ("z", 44), ("0", 5), ("1", 6), ("2", 7), ("3", 8), ("4", 9), ("5", 10), ("6", 11), ("7", 12), ("8", 13), ("9", 14), ("space", 62), ("tab", 63), ("escape", 114), ("enter", 57), ("backspace", 52), ("delete", 72), ("lshift", 60), ("rshift", 61), ("lctrl", 55), ("rctrl", 56), ("lalt", 50), ("ralt", 51), ("up", 82), ("down", 79), ("left", 80), ("right", 81), ("f1", 159), ("f2", 160), ("f3", 161), ("f4", 162), ("f5", 163), ("f6", 164), ("f7", 165), ("f8", 166), ("f9", 167), ("f10", 168), ("f11", 169), ("f12", 170), ];
#[must_use]
pub fn code_from_name(name: &str) -> Option<u32> {
NAMED_KEYS
.iter()
.find(|(n, _)| n.eq_ignore_ascii_case(name))
.map(|(_, code)| *code)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn names_are_unique_and_lower_case() {
let mut seen = std::collections::HashSet::new();
for (name, _) in NAMED_KEYS {
assert!(seen.insert(*name), "`{name}` is listed twice");
assert_eq!(*name, name.to_ascii_lowercase(), "`{name}` must be lower-case");
}
}
#[test]
fn codes_are_unique() {
let mut seen = std::collections::HashMap::new();
for (name, code) in NAMED_KEYS {
if let Some(other) = seen.insert(*code, *name) {
panic!("`{name}` and `{other}` both map to {code}");
}
}
}
#[test]
fn lookup_is_case_insensitive_and_total_over_the_table() {
for (name, code) in NAMED_KEYS {
assert_eq!(code_from_name(name), Some(*code));
assert_eq!(code_from_name(&name.to_ascii_uppercase()), Some(*code));
}
assert_eq!(code_from_name("no-such-key"), None);
}
#[test]
fn the_arrows_are_not_swapped() {
assert_eq!(code_from_name("up"), Some(82));
assert_eq!(code_from_name("down"), Some(79));
assert_eq!(code_from_name("left"), Some(80));
assert_eq!(code_from_name("right"), Some(81));
}
}