71 lines
1.8 KiB
Rust
71 lines
1.8 KiB
Rust
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<Fqsn, DefId>);
|
|
|
|
impl TrieKey for Fqsn {
|
|
fn encode_bytes(&self) -> Vec<u8> {
|
|
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<DefId> {
|
|
self.0.get(fqsn).cloned()
|
|
}
|
|
|
|
pub fn get_children(&self, fqsn: &Fqsn) -> Vec<Fqsn> {
|
|
let subtrie = match self.0.subtrie(fqsn) {
|
|
Some(s) => s,
|
|
None => return vec![],
|
|
};
|
|
let output: Vec<Fqsn> = 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);
|
|
}
|
|
}
|