use std::collections::HashMap;
use std::io::prelude::*;
use std::fs::File;
pub const KEYBOARD_DEFAULTS: &'static str = r#"
27 ESC
13 ENTER
32 SPACE
1073741906 UP
1073741905 DOWN
1073741904 LEFT
1073741903 RIGHT
"#;
#[derive(PartialEq, Eq)]
enum MappingState {
Keycode,
Action(i32),
}
#[derive(Debug)]
pub struct KeyboardMappings {
key_map: HashMap<i32, String>,
}
impl KeyboardMappings {
pub fn new(mappings: &str) -> KeyboardMappings {
let mapping_str = mappings.to_owned();
let token_stream: Vec<_> = mapping_str.split(|x| (x == ' ') || (x == '\n'))
.filter(|s| !s.trim().is_empty())
.collect();
let mut keyboard_mappings = KeyboardMappings { key_map: HashMap::new() };
let mut state = MappingState::Keycode;
for token in &token_stream {
match state {
MappingState::Keycode => {
if let Ok(keycode) = token.parse::<i32>() {
state = MappingState::Action(keycode);
}
}
MappingState::Action(keycode) => {
let action = token.clone().to_owned();
keyboard_mappings.key_map.insert(keycode, action);
state = MappingState::Keycode;
}
}
}
keyboard_mappings
}
pub fn from_file(path: &str) -> KeyboardMappings {
match File::open(path) {
Ok(ref mut f) => {
let mut mappings = String::new();
let _ = f.read_to_string(&mut mappings);
KeyboardMappings::new(&mappings[..])
}
_ => KeyboardMappings::new(KEYBOARD_DEFAULTS),
}
}
pub fn get_action(&self, keycode: i32) -> Option<&String> {
self.key_map.get(&keycode)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_basic() {
let s = "10 hello 11 world";
let mappings = KeyboardMappings::new(s);
assert_eq!(mappings.get_action(10), Some(&"hello".to_owned()));
assert_eq!(mappings.get_action(11), Some(&"world".to_owned()));
}
#[test]
fn parse_newlines() {
let s = "10 hello\n \n 11 world\n";
let mappings = KeyboardMappings::new(s);
assert_eq!(mappings.get_action(10), Some(&"hello".to_owned()));
assert_eq!(mappings.get_action(11), Some(&"world".to_owned()));
}
#[test]
fn parse_unbalanced() {
let s = "10 hello 11 world 12";
let mappings = KeyboardMappings::new(s);
assert_eq!(mappings.get_action(10), Some(&"hello".to_owned()));
assert_eq!(mappings.get_action(11), Some(&"world".to_owned()));
assert_eq!(mappings.get_action(12), None);
}
}