use crate::nibble_trie::NibbleTrie;
enum DynInner<T> {
U8 (NibbleTrie<Vec<u8>, T, u8, u16>),
U16(NibbleTrie<Vec<u8>, T, u16, u16>),
U32(NibbleTrie<Vec<u8>, T, u32, u16>),
U64(NibbleTrie<Vec<u8>, T, u64, u16>),
}
pub struct DynTrie<T> {
inner: DynInner<T>,
}
impl<T> DynTrie<T> {
pub fn new() -> Self {
DynTrie {
inner: DynInner::U8(NibbleTrie::new()),
}
}
pub fn get(&self, key: &[u8]) -> Option<&T> {
match &self.inner {
DynInner::U8(t) => t.get(key),
DynInner::U16(t) => t.get(key),
DynInner::U32(t) => t.get(key),
DynInner::U64(t) => t.get(key),
}
}
pub fn get_mut(&mut self, key: &[u8]) -> Option<&mut T> {
match &mut self.inner {
DynInner::U8(t) => t.get_mut(key),
DynInner::U16(t) => t.get_mut(key),
DynInner::U32(t) => t.get_mut(key),
DynInner::U64(t) => t.get_mut(key),
}
}
pub fn insert(&mut self, key: Vec<u8>, value: T) -> Result<usize, ()> {
loop {
let near = match &self.inner {
DynInner::U8(t) => t.near_capacity(),
DynInner::U16(t) => t.near_capacity(),
DynInner::U32(t) => t.near_capacity(),
DynInner::U64(t) => t.near_capacity(),
};
if !near {
break;
}
self.promote_inner();
}
match &mut self.inner {
DynInner::U8(t) => t.insert(key, value),
DynInner::U16(t) => t.insert(key, value),
DynInner::U32(t) => t.insert(key, value),
DynInner::U64(t) => t.insert(key, value),
}
}
pub fn len(&self) -> usize {
match &self.inner {
DynInner::U8(t) => t.len(),
DynInner::U16(t) => t.len(),
DynInner::U32(t) => t.len(),
DynInner::U64(t) => t.len(),
}
}
pub fn is_empty(&self) -> bool {
match &self.inner {
DynInner::U8(t) => t.is_empty(),
DynInner::U16(t) => t.is_empty(),
DynInner::U32(t) => t.is_empty(),
DynInner::U64(t) => t.is_empty(),
}
}
pub fn optimize(&mut self) {
match &mut self.inner {
DynInner::U8(t) => t.optimize(),
DynInner::U16(t) => t.optimize(),
DynInner::U32(t) => t.optimize(),
DynInner::U64(t) => t.optimize(),
}
}
pub fn ptr_size(&self) -> usize {
match &self.inner {
DynInner::U8(_) => 1,
DynInner::U16(_) => 2,
DynInner::U32(_) => 4,
DynInner::U64(_) => 8,
}
}
pub fn iter_fwd(&self, f: &mut dyn FnMut(&[u8], &T)) {
match &self.inner {
DynInner::U8(t) => {
let mut it = t.iter();
if let Some((k, v)) = it.current() { f(k, v); }
while let Some((k, v)) = it.next() { f(k, v); }
}
DynInner::U16(t) => {
let mut it = t.iter();
if let Some((k, v)) = it.current() { f(k, v); }
while let Some((k, v)) = it.next() { f(k, v); }
}
DynInner::U32(t) => {
let mut it = t.iter();
if let Some((k, v)) = it.current() { f(k, v); }
while let Some((k, v)) = it.next() { f(k, v); }
}
DynInner::U64(t) => {
let mut it = t.iter();
if let Some((k, v)) = it.current() { f(k, v); }
while let Some((k, v)) = it.next() { f(k, v); }
}
}
}
pub fn iter_rev(&self, f: &mut dyn FnMut(&[u8], &T)) {
match &self.inner {
DynInner::U8(t) => {
let mut it = t.iter_last();
if let Some((k, v)) = it.current() { f(k, v); }
while let Some((k, v)) = it.prev() { f(k, v); }
}
DynInner::U16(t) => {
let mut it = t.iter_last();
if let Some((k, v)) = it.current() { f(k, v); }
while let Some((k, v)) = it.prev() { f(k, v); }
}
DynInner::U32(t) => {
let mut it = t.iter_last();
if let Some((k, v)) = it.current() { f(k, v); }
while let Some((k, v)) = it.prev() { f(k, v); }
}
DynInner::U64(t) => {
let mut it = t.iter_last();
if let Some((k, v)) = it.current() { f(k, v); }
while let Some((k, v)) = it.prev() { f(k, v); }
}
}
}
pub fn demote(&mut self) -> Result<(), ()> {
let inner = std::mem::replace(&mut self.inner, DynInner::U8(NibbleTrie::new()));
match inner {
DynInner::U8(t) => {
self.inner = DynInner::U8(t);
Err(())
}
DynInner::U16(t) => {
match t.demote::<u8>() {
Ok(smaller) => {
self.inner = DynInner::U8(smaller);
Ok(())
}
Err(original) => {
self.inner = DynInner::U16(original);
Err(())
}
}
}
DynInner::U32(t) => {
match t.demote::<u16>() {
Ok(smaller) => {
self.inner = DynInner::U16(smaller);
Ok(())
}
Err(original) => {
self.inner = DynInner::U32(original);
Err(())
}
}
}
DynInner::U64(t) => {
match t.demote::<u32>() {
Ok(smaller) => {
self.inner = DynInner::U32(smaller);
Ok(())
}
Err(original) => {
self.inner = DynInner::U64(original);
Err(())
}
}
}
}
}
fn promote_inner(&mut self) {
let inner = std::mem::replace(&mut self.inner, DynInner::U8(NibbleTrie::new()));
self.inner = match inner {
DynInner::U8(t) => DynInner::U16(t.promote()),
DynInner::U16(t) => DynInner::U32(t.promote()),
DynInner::U32(t) => DynInner::U64(t.promote()),
DynInner::U64(t) => {
DynInner::U64(t)
}
};
}
}
impl<T> Default for DynTrie<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
#[path = "tests/dyn_trie.rs"]
mod tests;