use crate::engine::Transformation;
use crate::input_method::InputMethod;
use std::collections::HashMap;
#[derive(Clone, Debug)]
pub struct State {
pub transitions: [u32; 128],
pub composition: Box<[Transformation]>,
}
impl Default for State {
fn default() -> Self {
Self { transitions: [0; 128], composition: Box::new([]) }
}
}
pub struct Dfa {
pub states: Vec<State>,
pub composition_to_state: HashMap<Box<[Transformation]>, u32>,
}
impl Default for Dfa {
fn default() -> Self {
Self::new()
}
}
impl Dfa {
pub fn new() -> Self {
let mut dfa =
Self { states: Vec::with_capacity(1024), composition_to_state: HashMap::new() };
let empty_comp = Box::new([]);
dfa.states.push(State::default());
dfa.composition_to_state.insert(empty_comp, 0);
dfa
}
pub fn get_state(&self, id: u32) -> &State {
&self.states[id as usize]
}
pub fn add_state(&mut self, composition: &[Transformation]) -> u32 {
let comp_box: Box<[Transformation]> = composition.to_vec().into_boxed_slice();
if let Some(&id) = self.composition_to_state.get(&comp_box) {
return id;
}
let id = self.states.len() as u32;
self.states.push(State { transitions: [0; 128], composition: comp_box.clone() });
self.composition_to_state.insert(comp_box, id);
id
}
pub fn find_state(&self, composition: &[Transformation]) -> Option<u32> {
self.composition_to_state.get(composition).copied()
}
}
#[allow(dead_code)]
pub struct DfaCompiler<'a> {
pub input_method: &'a InputMethod,
pub flags: u32,
pub composition_to_state: HashMap<Vec<Transformation>, u32>,
pub dfa: Dfa,
}
#[allow(dead_code)]
impl<'a> DfaCompiler<'a> {
pub fn new(im: &'a InputMethod, flags: u32) -> Self {
let mut compiler =
Self { input_method: im, flags, composition_to_state: HashMap::new(), dfa: Dfa::new() };
compiler.composition_to_state.insert(Vec::new(), 0);
compiler
}
pub fn compile_common(&mut self) {
let vowels = ['a', 'e', 'i', 'o', 'u', 'y'];
let tones = ['s', 'f', 'r', 'x', 'j'];
for &v in &vowels {
self.simulate_key(v);
for &t in &tones {
self.simulate_sequence(&[v, t]);
}
}
let double_vowels = ["aa", "ee", "oo", "aw", "ow", "uw"];
for s in double_vowels {
self.simulate_str(s);
}
}
fn simulate_key(&mut self, key: char) -> u32 {
let mut engine = crate::Engine::with_config(
self.input_method.clone(),
crate::Config::from_flags(self.flags),
);
engine.process_key(key, crate::Mode::Vietnamese);
self.dfa.add_state(engine.active_slice())
}
fn simulate_sequence(&mut self, keys: &[char]) -> u32 {
let mut engine = crate::Engine::with_config(
self.input_method.clone(),
crate::Config::from_flags(self.flags),
);
for &k in keys {
engine.process_key(k, crate::Mode::Vietnamese);
}
self.dfa.add_state(engine.active_slice())
}
fn simulate_str(&mut self, s: &str) {
let mut engine = crate::Engine::with_config(
self.input_method.clone(),
crate::Config::from_flags(self.flags),
);
for k in s.chars() {
engine.process_key(k, crate::Mode::Vietnamese);
}
self.dfa.add_state(engine.active_slice());
}
}