#![no_std]
extern crate alloc;
mod bitmap;
mod key;
mod value_index;
pub use key::Key;
use alloc::collections::btree_map::BTreeMap;
use alloc::vec;
use alloc::vec::Vec;
use bitmap::*;
use core::cmp::min;
use core::marker::PhantomData;
use value_index::ValueIndex;
const STRIDE: u8 = 6;
#[derive(Debug, Clone, Default)]
pub struct Poptrie<K, V>
where
K: Key,
{
nodes: Vec<Node>,
leaves: Vec<ValueIndex>,
values: Vec<V>,
reference: Vec<BTreeMap<PrefixId, ValueIndex>>,
_marker: PhantomData<fn(K)>,
}
impl<K, V> Poptrie<K, V>
where
K: Key,
{
pub fn new() -> Self {
let mut root_node = Node::new(
#[cfg(test)]
Vec::new(),
1,
0,
);
root_node.leaf_bitmap.set(StrideId(0));
Poptrie::<K, V> {
values: Vec::new(),
nodes: vec![root_node], reference: vec![BTreeMap::new()], leaves: vec![ValueIndex::NONE], _marker: PhantomData,
}
}
pub fn insert(&mut self, key: K, key_length: u8, value: V) {
assert!(key_length <= K::BITS);
self.values.push(value);
let current_value_index =
ValueIndex::new((self.values.len() - 1) as u32);
let mut default_value_index = ValueIndex::NONE;
let mut key_offset = 0;
let mut parent_node_index = 0;
let mut parent_node = &self.nodes[parent_node_index];
while key_length >= key_offset + STRIDE {
let local_id = StrideId::from_key(key, key_offset, STRIDE);
let full_node_index = (parent_node.node_base
+ parent_node.node_bitmap.bitmap_index(local_id))
as usize;
let prefix_id = PrefixId::new(local_id.0, STRIDE).parent();
if let Some(default_index) =
find_leaf_lpm(&self.reference[parent_node_index], prefix_id)
{
default_value_index = default_index;
}
if !parent_node.node_bitmap.contains(local_id) {
let (next_node_base, next_leaf_base) =
self.find_next_base(full_node_index);
self.nodes.insert(
full_node_index,
Node::new(
#[cfg(test)]
[parent_node.debug_prefix.as_slice(), &[local_id]]
.concat(),
next_node_base,
next_leaf_base,
),
);
self.nodes[parent_node_index].node_bitmap.set(local_id);
for i in parent_node_index + 1..self.nodes.len() {
self.nodes[i].node_base += 1;
}
self.reference.insert(full_node_index, BTreeMap::new());
self.leaves
.insert(next_leaf_base as usize, default_value_index);
for i in full_node_index + 1..self.nodes.len() {
self.nodes[i].leaf_base += 1;
}
self.nodes[full_node_index].leaf_bitmap.set(StrideId(0));
}
parent_node_index = full_node_index;
parent_node = &self.nodes[parent_node_index];
key_offset += STRIDE;
}
let remaining_length = key_length - key_offset;
let prefix_id = PrefixId::from_key(key, key_offset, remaining_length);
self.reference[parent_node_index]
.insert(prefix_id, current_value_index);
if self.calculate_leaf_ranges(parent_node_index, default_value_index) {
self.update_children(parent_node_index, default_value_index);
}
}
pub fn lookup(&self, key: K) -> Option<&V> {
let mut key_offset = 0;
let mut parent_node_index = 0;
let mut parent_node = &self.nodes[parent_node_index];
let mut local_id = StrideId::from_key(key, key_offset, STRIDE);
while parent_node.node_bitmap.contains(local_id) {
let node_base = parent_node.node_base;
let node_offset = parent_node.node_bitmap.bitmap_index(local_id);
parent_node_index = (node_base + node_offset) as usize;
parent_node = &self.nodes[parent_node_index];
key_offset += STRIDE;
local_id = StrideId::from_key(key, key_offset, STRIDE);
}
let leaf_index = parent_node.leaf_bitmap.leafvec_index(local_id);
let leaf_base = parent_node.leaf_base;
let value_index = self.leaves[(leaf_base + leaf_index) as usize];
value_index.get().map(|i| &self.values[i as usize])
}
pub fn contains_key(&self, key: K, key_length: u8) -> bool {
let (parent_node, prefix_id, _) =
self.find_parent_node(key, key_length);
self.reference[parent_node].contains_key(&prefix_id)
}
pub fn remove(&mut self, key: K, key_length: u8) -> Option<V> {
let (parent_node, prefix_id, default_value_index) =
self.find_parent_node(key, key_length);
self.reference[parent_node].remove(&prefix_id).map(|v| {
if self.calculate_leaf_ranges(parent_node, default_value_index) {
self.update_children(parent_node, default_value_index);
}
for higher_v in self
.leaves
.iter_mut()
.chain(self.reference.iter_mut().flat_map(|s| s.values_mut()))
.filter(|higher_v| **higher_v > v)
{
higher_v.decrement();
}
self.values.remove(v.get().unwrap())
})
}
fn find_parent_node(
&self,
key: K,
key_length: u8,
) -> (usize, PrefixId, ValueIndex) {
let mut key_offset = 0;
let mut parent_node_index = 0;
let mut parent_node = &self.nodes[parent_node_index];
let mut default_value_index = ValueIndex::NONE;
while key_length >= key_offset + STRIDE {
let local_id = StrideId::from_key(key, key_offset, STRIDE);
let prefix_id = PrefixId::new(local_id.0, STRIDE).parent();
if let Some(default_index) =
find_leaf_lpm(&self.reference[parent_node_index], prefix_id)
{
default_value_index = default_index;
}
if !parent_node.node_bitmap.contains(local_id) {
break;
}
parent_node_index = (parent_node.node_base
+ parent_node.node_bitmap.bitmap_index(local_id))
as usize;
parent_node = &self.nodes[parent_node_index];
key_offset += STRIDE;
}
let remaining_length = min(key_length - key_offset, STRIDE - 1);
let prefix_id = PrefixId::from_key(key, key_offset, remaining_length);
(parent_node_index, prefix_id, default_value_index)
}
fn find_next_base(&self, next_node_index: usize) -> (u32, u32) {
let last_node = &self.nodes[next_node_index - 1];
let next_leaf_base =
last_node.leaf_base + last_node.leaf_bitmap.pop_count();
let next_node_base =
last_node.node_base + last_node.node_bitmap.pop_count();
(next_node_base, next_leaf_base)
}
fn calculate_leaf_ranges(
&mut self,
node_index: usize,
default_value_index: ValueIndex,
) -> bool {
let mut changed = false;
let mut leaves_inserted = 0;
let leaf_base = self.nodes[node_index].leaf_base as usize;
for prefix in 0..(1 << (STRIDE - 1)) {
let correct_value = find_leaf_lpm(
&self.reference[node_index],
PrefixId::new(prefix, STRIDE - 1),
)
.unwrap_or(default_value_index);
let leaf_id = StrideId(prefix << 1);
let leafvec_index =
self.nodes[node_index].leaf_bitmap.leafvec_index(leaf_id);
let current_value = self.leaves[leaf_base + leafvec_index as usize];
if current_value != correct_value {
changed = true;
let leaf_bitmap_index = leaf_base
+ self.nodes[node_index].leaf_bitmap.bitmap_index(leaf_id)
as usize;
if !self.nodes[node_index].leaf_bitmap.contains(leaf_id) {
leaves_inserted += 1;
self.leaves.insert(leaf_bitmap_index, correct_value);
self.nodes[node_index].leaf_bitmap.set(leaf_id);
} else {
self.leaves[leaf_bitmap_index] = correct_value;
}
}
}
for i in node_index + 1..self.nodes.len() {
self.nodes[i].leaf_base += leaves_inserted;
}
changed
}
fn update_children(
&mut self,
parent_node_index: usize,
parent_default: ValueIndex,
) {
let node_base = self.nodes[parent_node_index].node_base as usize;
for prefix in 0..(1 << (STRIDE)) {
let child_id = StrideId(prefix);
if self.nodes[parent_node_index].node_bitmap.contains(child_id) {
let child_node_index = self.nodes[parent_node_index]
.node_bitmap
.bitmap_index(child_id);
let full_child_node_index =
node_base + child_node_index as usize;
let prefix_id = PrefixId::new(child_id.0, STRIDE).parent();
let default_value = find_leaf_lpm(
&self.reference[parent_node_index],
prefix_id,
)
.unwrap_or(parent_default);
if self
.calculate_leaf_ranges(full_child_node_index, default_value)
{
self.update_children(full_child_node_index, default_value);
}
}
}
}
}
#[derive(Debug, Clone)]
struct Node {
#[cfg(test)]
debug_prefix: Vec<StrideId>,
node_bitmap: Bitmap<StrideId>,
leaf_bitmap: Bitmap<StrideId>,
node_base: u32,
leaf_base: u32,
}
impl Node {
fn new(
#[cfg(test)] debug_prefix: Vec<StrideId>,
node_base: u32,
leaf_base: u32,
) -> Self {
Node {
#[cfg(test)]
debug_prefix,
node_bitmap: Bitmap::new(),
leaf_bitmap: Bitmap::new(),
node_base,
leaf_base,
}
}
}