From f45be3b3fd7783b4606e8a3e6efebc555a27cf42 Mon Sep 17 00:00:00 2001 From: shiro Date: Mon, 4 Dec 2023 17:23:44 +0900 Subject: [PATCH] Improve text mapper performance --- src/mapper/text_mapper.rs | 75 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 5 deletions(-) diff --git a/src/mapper/text_mapper.rs b/src/mapper/text_mapper.rs index 46c3083..4360178 100644 --- a/src/mapper/text_mapper.rs +++ b/src/mapper/text_mapper.rs @@ -1,3 +1,4 @@ +use nom::Slice; use crate::*; use crate::mapper::RuntimeKeyAction; use crate::mapper::mapping_functions::*; @@ -6,7 +7,7 @@ use crate::subscriber::{SubscribeEvent, Subscriber}; use crate::xkb::XKBTransformer; use crate::xkb_transformer_registry::{TransformerParams, XKB_TRANSFORMER_REGISTRY}; -type Mappings = HashMap>; +type Mappings = SuffixTree>; #[derive(Default)] @@ -34,6 +35,66 @@ fn _map(from: &KeyClickActionWithMods, to: Vec) -> Vec { + root: HashMap>, +} + +impl SuffixTree { + pub fn new() -> Self { Self { root: HashMap::new() } } + + pub fn insert(&mut self, key: String, value: Value) { + self.root.entry(key.chars().last().unwrap()).or_default().insert(&key[0..key.len() - 1], value); + } + + pub fn get(&self, key: &String) -> Option<&Value> { + self.root.get(&key.chars().last().unwrap()).and_then(|x| x.get(&key[0..key.len() - 1])) + } +} + +impl Clone for SuffixTree { + fn clone(&self) -> Self { Self { root: self.root.clone() } } +} + +struct SuffixTreeNode { + value: Option, + children: HashMap>, +} + +impl Default for SuffixTreeNode { + fn default() -> Self { Self { value: None, children: HashMap::new() } } +} + +impl SuffixTreeNode { + pub fn new() -> Self { + Self { value: None, children: HashMap::new() } + } + + pub fn insert(&mut self, key: &str, value: Value) { + if let Some(ch) = key.chars().last() { + self.children.entry(ch).or_default().insert(key.slice(0..key.len() - 1), value); + } else { + self.value = Some(value); + } + } + + pub fn get(&self, key: &str) -> Option<&Value> { + if let Some(ch) = key.chars().last() { + self.children.get(&ch).and_then(|x| x.get(key.slice(0..key.len() - 1))) + } else { + self.value.as_ref() + } + } +} + +impl Clone for SuffixTreeNode { + fn clone(&self) -> Self { + Self { + value: self.value.clone(), + children: self.children.clone(), + } + } +} #[derive(Default)] struct Inner { @@ -73,7 +134,8 @@ impl Inner { if let Some(key) = key { state.window.push(key.chars().next().unwrap()); - if state.window.len() > 5 { + // TODO set window size dynamically + if state.window.len() > 32 { state.window.remove(0); } @@ -110,7 +172,7 @@ impl Inner { } RuntimeKeyAction::ReleaseRestoreModifiers(from_flags, to_flags, to_type) => { let new_events = release_restore_modifiers( - &state.modifiers, from_flags, to_flags, to_type, + &state.modifiers, &from_flags, &to_flags, &to_type, ); // events.append(&mut new_events); for ev in new_events { @@ -195,8 +257,11 @@ impl TextMapper { }) } - pub fn map(&mut self, from: String, to: String) -> PyResult<()> { + if from.len() > 32 { + return Err(PyRuntimeError::new_err("'from' side cannot be longer than 32 character")); + } + let from_seq: Vec = parse_key_sequence(&from, Some(&self.transformer)) .map_err(|err| PyRuntimeError::new_err(format!( "mapping error on the 'from' side:\n{}", @@ -210,7 +275,7 @@ impl TextMapper { } }) .collect::>>() - .unwrap(); + .ok_or_else(|| PyRuntimeError::new_err("invalid key sequence"))?; let to = parse_key_sequence(&to, Some(&self.transformer)) .map_err(|err| PyRuntimeError::new_err(format!(