use std::collections::HashMap;
struct TrieNode<V> {
children: HashMap<String, TrieNode<V>>,
module: Option<V>,
}
impl<V> TrieNode<V> {
fn new() -> Self {
TrieNode {
children: HashMap::new(),
module: None,
}
}
}
pub struct Trie<V> {
root: TrieNode<V>,
count: i32,
cache: HashMap<String, Option<V>>,
}
impl<V: Clone> Trie<V> {
pub fn new() -> Self {
Trie {
root: TrieNode::new(),
count: 0,
cache: HashMap::new(),
}
}
pub fn len(&self) -> i32 {
self.count
}
pub fn insert(&mut self, pattern: &str, module: V) {
let segments: Vec<&str> = pattern.split("::").collect();
let mut node = &mut self.root;
for segment in segments {
node = node.children.entry(segment.to_string()).or_insert_with(TrieNode::new);
}
node.module = Some(module);
self.count += 1;
}
pub fn get(&mut self, input: &str) -> Option<&V> {
if self.cache.contains_key(input) {
return self.cache.get(input).and_then(|opt|opt.as_ref());
}
let segments: Vec<&str> = input.split("::").collect();
let mut node = &self.root;
let mut last_matched_module: Option<&V> = None;
for segment in segments {
if let Some(child) = node.children.get("*") {
if let Some(ref module) = child.module {
last_matched_module = Some(module);
}
}
if let Some(child) = node.children.get(segment) {
node = child;
if let Some(ref module) = node.module {
last_matched_module = Some(module);
}
} else {
break;
}
}
if let Some(v) = last_matched_module {
self.cache.insert(input.to_string(), Some(v.clone()));
}
self.cache.get(input).and_then(|opt| opt.as_ref())
}
}