#![forbid(unsafe_code, missing_docs, missing_debug_implementations)]
cfg_if::cfg_if! {
if #[cfg(feature ="std")] {
extern crate std;
use std::vec::Vec;
}
else {
extern crate alloc;
use alloc::vec::Vec;
}
}
#[derive(Debug)]
pub struct KeyExistsError;
#[derive(Debug)]
pub struct KeyNotFoundError;
#[derive(Debug, PartialEq, Eq)]
pub struct Trie<K: Eq + Clone, V> {
root: TrieNode<K, V>,
}
#[derive(Debug, PartialEq, Eq)]
struct TrieNode<K: Eq + Clone, V> {
children: Vec<TrieNode<K, V>>,
value: Option<V>,
prefix: Box<[K]>,
}
impl<K: Eq + Clone, V> Trie<K, V> {
pub fn new() -> Self {
Trie {
root: TrieNode {
value: None,
prefix: Box::new([]),
children: Vec::new(),
},
}
}
#[inline]
fn get(&self, key: &[K]) -> Option<&V> {
self.root.get(key)
}
#[inline]
pub fn get_mut(&mut self, key: &[K]) -> Option<&mut V> {
self.root.get_mut(key)
}
#[inline]
pub fn has(&self, key: &[K]) -> bool {
self.get(key).is_some()
}
#[inline]
pub fn put(&mut self, key: &[K], val: V) -> Option<V> {
self.root.insert(key, val)
}
#[inline]
pub fn try_put(&mut self, key: &[K], val: V) -> Result<(), KeyExistsError> {
match self.has(key) {
true => Err(KeyExistsError),
false => {
self.put(key, val);
Ok(())
}
}
}
#[inline]
pub fn remove(&mut self, key: &[K]) -> Result<V, KeyNotFoundError> {
match self.root.remove(key) {
None => Err(KeyNotFoundError),
Some(data) => Ok(data),
}
}
#[inline]
pub fn size(&self) -> usize {
self.root.size()
}
}
impl<V> Trie<u8, V> {
pub fn put_str(&mut self, key: &str, val: V) -> Option<V> {
self.put(key.as_bytes(), val)
}
pub fn try_put_str(&mut self, key: &str, val: V) -> Result<(), KeyExistsError> {
self.try_put(key.as_bytes(), val)
}
pub fn get_str(&mut self, key: &str) -> Option<&V> {
self.get(key.as_bytes())
}
pub fn get_mut_str(&mut self, key: &str) -> Option<&mut V> {
self.get_mut(key.as_bytes())
}
pub fn has_str(&mut self, key: &str) -> bool {
self.has(key.as_bytes())
}
pub fn remove_str(&mut self, key: &str) -> Result<V, KeyNotFoundError> {
self.remove(key.as_bytes())
}
}
impl<K: Eq + Clone, V> TrieNode<K, V> {
fn size(&self) -> usize {
let mut size = 1;
for other in self.children.iter() {
size += other.size();
}
return size;
}
fn get(&self, key: &[K]) -> Option<&V> {
if key == self.prefix.as_ref() {
return self.value.as_ref();
}
let rest = &key[self.prefix.len()..];
let leaf = self.leaf(rest);
match leaf {
None => None,
Some(node) => node.get(rest),
}
}
fn leaf(&self, key: &[K]) -> Option<&Self> {
for node in self.children.iter() {
if key.starts_with(node.prefix.as_ref()) {
return Some(&node);
}
}
None
}
fn get_mut(&mut self, key: &[K]) -> Option<&mut V> {
if key == self.prefix.as_ref() {
return self.value.as_mut();
}
let rest = &key[self.prefix.len()..];
let leaf = self.leaf_mut(rest);
match leaf {
None => None,
Some(node) => node.get_mut(rest),
}
}
fn leaf_mut(&mut self, key: &[K]) -> Option<&mut Self> {
for node in self.children.iter_mut() {
if key.starts_with(&node.prefix) {
return Some(node);
}
}
None
}
fn insert(&mut self, key: &[K], value: V) -> Option<V> {
if key == self.prefix.as_ref() {
return self.value.replace(value);
}
let rest = &key[self.prefix.len()..];
let leaf = self.leaf_mut(rest);
if leaf.is_some() {
return leaf.unwrap().insert(rest, value);
}
let split = self.insert_split_target(rest);
if split.is_some() {
let (idx, node) = split.unwrap();
let inject = TrieNode {
prefix: (&rest[(rest.len() - 1)..(node.prefix.len() - rest.len())])
.to_owned()
.into_boxed_slice(),
children: Vec::new(),
value: Some(value),
};
let moved = std::mem::replace(&mut self.children[idx], inject);
self.children[idx].children.push(moved);
return None;
}
let inject = TrieNode {
prefix: rest.to_owned().into_boxed_slice(),
children: Vec::new(),
value: Some(value),
};
self.children.push(inject);
return None;
}
fn insert_split_target(&mut self, key: &[K]) -> Option<(usize, &mut Self)> {
self.children
.iter_mut()
.enumerate()
.find(|(_idx, node)| node.prefix.starts_with(key))
}
fn remove(&mut self, key: &[K]) -> Option<V> {
if key == self.prefix.as_ref() {
return self.value.take();
}
self.remove_internal(&key[self.prefix.len()..])
}
fn remove_internal(&mut self, key: &[K]) -> Option<V> {
let rest = &key[self.prefix.len()..];
let leaf = self.leaf_mut(rest);
if leaf.is_none() {
return None;
}
let leaf = leaf.unwrap();
if leaf.prefix.as_ref() != rest {
return leaf.remove_internal(rest);
}
let evicted = leaf.value.take();
match leaf.children.len() {
0 => {
let prefix = leaf.prefix.clone();
self.evict_node_with_prefix(prefix.as_ref());
}
1 => {
leaf.take_below();
}
_ => {
}
}
match self.children.len() {
1 => {
self.take_below();
}
_ => {
}
}
evicted
}
fn evict_node_with_prefix(&mut self, prefix: &[K]) {
self.children.swap_remove(
self.children
.iter()
.enumerate()
.find(|(_idx, n)| n.prefix.as_ref() == prefix)
.unwrap()
.0,
);
}
fn take_below(&mut self) {
assert!(self.children.len() == 1);
let taken = std::mem::replace(&mut self.children[0].children, Vec::new());
let node = self.children.remove(0);
let prefix = node.prefix.to_owned();
std::mem::drop(node);
self.children = taken;
self.prefix = [self.prefix.as_ref(), prefix.as_ref()].concat().into();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn insertion_retrieval() {
let mut trie = Trie::new();
let v1 = vec!["a", "ab", "ac", "b", "c", "abc", "abcde", "abced"];
let v2 = vec![1, 2, 3, 4, 5, 6, 7, 9];
for i in 0..8 {
trie.put_str(v1[i], v2[i]);
}
for i in 0..8 {
assert_eq!(trie.get_str(v1[i]), Some(&v2[i]));
}
assert_eq!(trie.size(), 9);
trie.put_str(v1[3], 33);
assert_eq!(trie.get_str(v1[3]), Some(&33));
assert_eq!(trie.size(), 9);
}
#[test]
fn insertion_deletion() {
let mut trie = Trie::new();
let v1 = vec!["a", "ab", "ac", "b", "c", "abc", "abcde", "abced"];
let v2 = vec![1, 2, 3, 4, 5, 6, 7, 9];
for i in 0..8 {
trie.put_str(v1[i], v2[i]);
}
for i in 0..8 {
assert_eq!(trie.get_str(v1[i]), Some(&v2[i]));
}
assert_eq!(trie.size(), 9);
let removed = trie.remove_str("abcd");
assert!(removed.is_err());
let removed = trie.remove_str("abcde");
assert_eq!(removed.ok(), Some(7));
assert_eq!(trie.size(), 7);
let removed: Result<i32, KeyNotFoundError> = trie.remove_str("c");
assert_eq!(removed.ok(), Some(5));
assert_eq!(trie.size(), 6);
let removed = trie.remove_str("abcde");
assert!(removed.is_err());
assert_eq!(trie.size(), 6);
}
#[test]
fn i32_tests() {
let mut trie = Trie::new();
let v1: Vec<Box<[i32]>> = vec![[1].into(), [2].into(), [3].into(), [4].into(), [2, 3, 4].into(), [2, 3, 4, 5].into(), [3, 5, 1].into(), [1, 11, 111].into(), [1, 111, 11].into()];
let v2 = vec!["a", "b", "c", "d", "e", "f", "g" ,"h", "i"];
for i in 0..v1.len() {
trie.put(v1[i].as_ref(), v2[i].to_owned());
}
for i in 0..v1.len() {
assert_eq!(trie.get(v1[i].as_ref()), Some(&v2[i].to_owned()));
}
}
}