use std::collections::hash_map::Entry;
use std::collections::HashMap;
#[derive(Default, Debug)]
pub(crate) struct TrieNode {
pub children: HashMap<char, TrieNode>,
}
impl TrieNode {
pub fn insert(&mut self, mut content: impl Iterator<Item = char>) {
if let Some(ch) = content.next() {
self.children.entry(ch).or_default().insert(content)
}
}
pub fn get_node(&self, mut prefix: impl Iterator<Item = char>) -> Option<&Self> {
if let Some(ch) = prefix.next() {
self.children.get(&ch)?.get_node(prefix)
} else {
Some(self)
}
}
pub fn iter_content(&self) -> ChildIter {
ChildIter::new(self)
}
pub fn remove(&mut self, mut content: impl Iterator<Item = char>) -> Option<()> {
if let Some(ch) = content.next() {
let node = self.children.get_mut(&ch)?;
node.remove(content)?;
if node.children.is_empty() {
self.children.remove(&ch);
}
}
Some(())
}
fn remove_node(&mut self, path: &[char]) -> Option<TrieNode> {
if let Some((&first, rest)) = path.split_first() {
match self.children.entry(first) {
Entry::Vacant(_) => None,
Entry::Occupied(e) => {
if rest.is_empty() {
Some(e.remove())
} else {
let node = e.into_mut();
node.remove_node(rest)
}
}
}
} else {
None
}
}
pub fn remove_suffixes(&mut self, prefix: impl Iterator<Item = char>) -> Option<TrieNode> {
let path: Vec<char> = prefix.collect();
self.remove_node(&path)
}
}
pub(crate) struct ChildIter<'a> {
remaining: Vec<(&'a TrieNode, String)>,
}
impl ChildIter<'_> {
fn new(node: &TrieNode) -> ChildIter {
ChildIter {
remaining: vec![(node, String::new())],
}
}
}
impl<'a> Iterator for ChildIter<'a> {
type Item = String;
fn next(&mut self) -> Option<Self::Item> {
if let Some((node, s)) = self.remaining.pop() {
for (&ch, child) in &node.children {
let mut prefix = s.clone();
prefix.push(ch);
self.remaining.push((child, prefix));
}
Some(s)
} else {
None
}
}
}