//! Implements a trie on T9 numpads //! //! # T9: //! 1: 2:abc 3:def //! 4:ghi 5:jkl 6:mno //! 7:pqrs 8:tuv 9:wxyz use std::{ collections::VecDeque, ops::{Index, IndexMut}, }; #[derive(Debug, Default)] pub struct Trie9 { pub link: Option>, pub leaf: Vec, } impl Trie9 { pub fn new() -> Self { Self::default() } pub fn insert(&mut self, string: &str) -> bool { let Some(trie) = self.at_mut(string.chars()) else { return false; }; trie.leaf.push(string.into()); true } pub fn get(&self, index: T9) -> Option<&Trie9> { self.link.as_ref()?.get(index as usize) } pub fn get_mut(&mut self, index: T9) -> Option<&mut Trie9> { self.link.as_mut()?.get_mut(index as usize) } pub fn get_or_insert(&mut self, index: T9) -> &mut Trie9 { self.link .get_or_insert_default() .get_mut(index as usize) .expect("link exists at all T9 indices") } pub fn at(&self, code: Iter) -> Option<&Self> where Iter: IntoIterator, T: TryInto, { let mut code = code.into_iter(); match code.next() { None => Some(self), Some(link) => self.get(link.try_into().ok()?)?.at(code), } } pub fn at_mut(&mut self, code: Iter) -> Option<&mut Self> where Iter: IntoIterator, T: TryInto, { let mut code = code.into_iter(); match code.next() { None => Some(self), Some(link) => self.get_or_insert(link.try_into().ok()?).at_mut(code), } } pub fn iter<'t>(&'t self) -> Trie9Iter<'t> { Trie9Iter::new(self) } } #[derive(Clone, Debug)] pub struct Trie9Iter<'t9> { queue: VecDeque<&'t9 Trie9>, items: std::slice::Iter<'t9, String>, } impl<'t> Trie9Iter<'t> { pub fn new(trie: &'t Trie9) -> Self { Self { queue: VecDeque::from([trie]), items: Default::default() } } } impl<'t> Iterator for Trie9Iter<'t> { type Item = &'t str; fn next(&mut self) -> Option { let Self { queue, items } = self; if let Some(item) = items.next() { return Some(item.as_str()); } let Trie9 { link, leaf } = queue.pop_front()?; *items = leaf.iter(); queue.extend(link.iter().flat_map(|v| v.iter())); self.next() } } impl<'t> IntoIterator for &'t Trie9 { type IntoIter = Trie9Iter<'t>; type Item = &'t str; fn into_iter(self) -> Self::IntoIter { Self::IntoIter::new(self) } } #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum T9 { T2, T3, T4, T5, T6, T7, T8, T9, } impl From for u8 { fn from(value: T9) -> Self { value as u8 + 2 } } impl From for char { fn from(value: T9) -> Self { match value { T9::T2 => '2', T9::T3 => '3', T9::T4 => '4', T9::T5 => '5', T9::T6 => '6', T9::T7 => '7', T9::T8 => '8', T9::T9 => '9', } } } impl TryFrom for T9 { type Error = char; fn try_from(value: char) -> Result { Ok(match value { '2' | 'A'..='C' | 'a'..='c' | 'À'..='Æ' | 'à'..='æ' | 'Ç' | 'ç' => Self::T2, '3' | 'D'..='F' | 'd'..='f' | 'È'..='Ë' | 'è'..='ë' => Self::T3, '4' | 'G'..='I' | 'g'..='i' | 'Ì'..='Ï' | 'ì'..='ï' => Self::T4, '5' | 'J'..='L' | 'j'..='l' | '1' => Self::T5, '6' | 'M'..='O' | 'm'..='o' | 'Ò'..='Ø' | 'ò'..='ø' | '0' => Self::T6, '7' | 'P'..='S' | 'p'..='s' => Self::T7, '8' | 'T'..='V' | 't'..='v' | 'Ù'..='Ü' | 'ù'..='ü' => Self::T8, '9' | 'W'..='Z' | 'w'..='z' => Self::T9, _ => Err(value)?, }) } } impl Index for Trie9 { type Output = Trie9; fn index(&self, index: T9) -> &Self::Output { let Some(link) = self.get(index) else { panic!("No Trie9 at index {index:?}"); }; link } } impl IndexMut for Trie9 { fn index_mut(&mut self, index: T9) -> &mut Self::Output { self.get_or_insert(index) } }