added basic unit tests

This commit is contained in:
2025-07-30 11:03:19 +08:00
parent 575281869b
commit 3d2a08801f
10 changed files with 259 additions and 143 deletions
+48 -69
View File
@@ -1,9 +1,9 @@
use std::collections::BTreeSet;
use std::marker::PhantomData;
use super::keychecker::KeyChecker;
use super::trienode::TrieKey;
use super::trienode::TrieNode;
use std::collections::BTreeSet;
use std::iter::Iterator;
use std::marker::PhantomData;
pub enum VisitOutcome {
Continue,
@@ -16,47 +16,49 @@ where
KEY: TrieKey,
KEYCHECKER: KeyChecker<KEY>,
{
pub (crate) nodes: Vec<TrieNode<KEY>>,
pub(crate) nodes: Vec<TrieNode<KEY>>,
tails: BTreeSet<usize>,
checker: PhantomData<KEYCHECKER>,
}
impl<KEY, KEYCHECKER> Default for Trie<KEY, KEYCHECKER>
where
KEY: TrieKey,
KEYCHECKER: KeyChecker<KEY>,
{
fn default() -> Self {
Trie {
nodes: vec![TrieNode::new0(None)],
tails: BTreeSet::new(),
checker: PhantomData,
}
}
}
impl<KEY, KEYCHECKER> Trie<KEY, KEYCHECKER>
where
KEY: TrieKey,
KEYCHECKER: KeyChecker<KEY>,
{
pub fn empty() -> Trie<KEY, KEYCHECKER> {
Trie {
nodes: vec![TrieNode::new0(None)],
tails: BTreeSet::new(),
checker: PhantomData::default(),
}
}
pub fn trie_from_words<T: IntoIterator, U: IntoIterator>(
wordlist: U,
) -> Trie<KEY, KEYCHECKER>
pub fn trie_from_words<T, U>(wordlist: U) -> Trie<KEY, KEYCHECKER>
where
T: IntoIterator<Item = KEY>,
U: IntoIterator<Item = T>,
{
let mut result = Trie::empty();
let mut result = Trie::default();
for word in wordlist {
result.add(word);
}
result
}
pub (crate) fn get_node_mut(&mut self, index: usize) -> &mut TrieNode<KEY> {
pub(crate) fn get_node_mut(&mut self, index: usize) -> &mut TrieNode<KEY> {
&mut self.nodes[index]
}
pub (crate) fn get_node(&self, index: usize) -> &TrieNode<KEY> {
pub(crate) fn get_node(&self, index: usize) -> &TrieNode<KEY> {
&self.nodes[index]
}
pub (crate) fn nodes(&self) -> usize {
pub(crate) fn nodes(&self) -> usize {
self.nodes.len()
}
@@ -98,7 +100,7 @@ where
result_index
}
pub fn add<T: IntoIterator>(&mut self, path: T) -> (bool, usize)
pub fn add<T>(&mut self, path: T) -> (bool, usize)
where
T: IntoIterator<Item = KEY>,
{
@@ -106,22 +108,15 @@ where
let mut pnode = 0;
'wordLoop: for key in path {
let mut cnode = self.get_node(pnode).child;
loop {
match cnode {
Some(cnode_index) => {
let cnode_node = self.get_node(cnode_index);
if KEYCHECKER::check(cnode_node.key, Some(key)) {
pnode = cnode_index;
continue 'wordLoop;
} else if self.get_node(cnode_index).next.is_none() {
break;
} else {
cnode = self.get_node(cnode_index).next;
}
}
None => {
break;
}
while let Some(cnode_index) = cnode {
let cnode_node = self.get_node(cnode_index);
if KEYCHECKER::check(cnode_node.key, Some(key)) {
pnode = cnode_index;
continue 'wordLoop;
} else if self.get_node(cnode_index).next.is_none() {
break;
} else {
cnode = self.get_node(cnode_index).next;
}
}
pnode = self.add_node(Some(key), pnode, cnode);
@@ -131,17 +126,10 @@ where
let tail = self.add_node(None, pnode, None);
self.tails.insert(tail);
let mut node = Some(tail);
loop {
match node {
Some(n) => {
let current_node = self.get_node_mut(n);
current_node.ref_count += 1;
node = current_node.parent;
}
None => {
break;
}
}
while let Some(n) = node {
let current_node = self.get_node_mut(n);
current_node.ref_count += 1;
node = current_node.parent;
}
(true, tail)
} else {
@@ -177,31 +165,23 @@ where
result
}
pub fn lineal_descendant(&self, start: usize) -> Vec<&KEY> {
let mut chars: Vec<&KEY> = vec![];
pub fn lineal_descendant(&self, start: usize) -> impl Iterator<Item = &KEY> {
let mut nodes: Vec<usize> = vec![];
let mut node_option = Some(start);
loop {
match node_option {
Some(node) => {
let key = &self.get_node(node).key;
match key {
Some(key) => {
chars.push(key);
}
None => {}
}
node_option = self.get_node(node).parent;
}
None => {
break;
}
while let Some(node) = node_option {
let key = &self.get_node(node).key;
if key.is_some() {
nodes.push(node);
}
node_option = self.get_node(node).parent;
}
chars.reverse();
chars
nodes
.into_iter()
.rev()
.map(|node_index| self.get_node(node_index).key.as_ref().unwrap())
}
pub (crate) fn walk<CB1, CB2>(&self, mut visit_pre: CB1, mut visit_post: CB2)
pub(crate) fn walk<CB1, CB2>(&self, mut visit_pre: CB1, mut visit_post: CB2)
where
CB1: FnMut(&Vec<usize>) -> VisitOutcome,
CB2: FnMut(&Vec<usize>),
@@ -243,4 +223,3 @@ where
&self.tails
}
}