use std::{ collections::hash_map::DefaultHasher, hash::{Hash, Hasher}, }; use radix_trie::{Trie, TrieCommon, TrieKey}; use super::{DefId, Fqsn, ScopeSegment}; #[derive(Debug)] pub struct SymbolTrie(Trie); impl TrieKey for Fqsn { fn encode_bytes(&self) -> Vec { let mut hasher = DefaultHasher::new(); let mut output = vec![]; for segment in self.scopes.iter() { let ScopeSegment::Name(s) = segment; s.as_bytes().hash(&mut hasher); output.extend_from_slice(&hasher.finish().to_be_bytes()); } output } } impl SymbolTrie { pub fn new() -> SymbolTrie { SymbolTrie(Trie::new()) } pub fn insert(&mut self, fqsn: &Fqsn, def_id: DefId) { self.0.insert(fqsn.clone(), def_id); } pub fn lookup(&self, fqsn: &Fqsn) -> Option { self.0.get(fqsn).cloned() } pub fn get_children(&self, fqsn: &Fqsn) -> Vec { let subtrie = match self.0.subtrie(fqsn) { Some(s) => s, None => return vec![], }; let output: Vec = subtrie.keys().filter(|cur_key| **cur_key != *fqsn).cloned().collect(); output } } #[cfg(test)] mod test { use super::*; use crate::symbol_table::Fqsn; fn make_fqsn(strs: &[&str]) -> Fqsn { Fqsn::from_strs(strs) } #[test] fn test_trie_insertion() { let id = DefId::default(); let mut trie = SymbolTrie::new(); trie.insert(&make_fqsn(&["unrelated", "thing"]), id); trie.insert(&make_fqsn(&["outer", "inner"]), id); trie.insert(&make_fqsn(&["outer", "inner", "still_inner"]), id); let children = trie.get_children(&make_fqsn(&["outer", "inner"])); assert_eq!(children.len(), 1); } }