2019-10-17 03:15:39 -07:00
|
|
|
use std::rc::Rc;
|
|
|
|
use radix_trie::{Trie, TrieCommon, TrieKey};
|
|
|
|
use super::{ScopeSegmentKind, ScopeSegment, FullyQualifiedSymbolName};
|
|
|
|
use std::hash::{Hasher, Hash};
|
|
|
|
use std::collections::hash_map::DefaultHasher;
|
|
|
|
|
2019-10-18 09:54:56 -07:00
|
|
|
#[derive(Debug)]
|
2019-10-17 03:15:39 -07:00
|
|
|
pub struct SymbolTrie(Trie<FullyQualifiedSymbolName, ()>);
|
|
|
|
|
|
|
|
impl TrieKey for FullyQualifiedSymbolName {
|
|
|
|
fn encode_bytes(&self) -> Vec<u8> {
|
|
|
|
let mut hasher = DefaultHasher::new();
|
|
|
|
let mut output = vec![];
|
|
|
|
let FullyQualifiedSymbolName(scopes) = self;
|
|
|
|
for segment in scopes.iter() {
|
|
|
|
segment.name.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: &FullyQualifiedSymbolName) {
|
|
|
|
self.0.insert(fqsn.clone(), ());
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_children(&self, fqsn: &FullyQualifiedSymbolName) -> Vec<FullyQualifiedSymbolName> {
|
|
|
|
let subtrie = match self.0.subtrie(fqsn) {
|
|
|
|
Some(s) => s,
|
|
|
|
None => return vec![]
|
|
|
|
};
|
2019-10-18 09:54:56 -07:00
|
|
|
let output: Vec<FullyQualifiedSymbolName> = subtrie.keys().filter(|cur_key| **cur_key != *fqsn).map(|fqsn| fqsn.clone()).collect();
|
2019-10-17 03:15:39 -07:00
|
|
|
output
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_trie_insertion() {
|
|
|
|
let mut trie = SymbolTrie::new();
|
|
|
|
|
|
|
|
trie.insert(&fqsn!("unrelated"; ty, "thing"; tr));
|
|
|
|
trie.insert(&fqsn!("outer"; ty, "inner"; tr));
|
|
|
|
trie.insert(&fqsn!("outer"; ty, "inner"; ty, "still_inner"; tr));
|
|
|
|
|
|
|
|
let children = trie.get_children(&fqsn!("outer"; ty, "inner"; tr));
|
|
|
|
assert_eq!(children.len(), 2);
|
|
|
|
}
|