#![no_std]
extern crate alloc;
mod address;
mod bitmap;
mod iter;
mod prefix;
mod value_index;
pub use address::Address;
pub use iter::{IntoIter, Iter, IterMut, Keys, Values, ValuesMut};
pub use prefix::Prefix;
use alloc::collections::btree_map::BTreeMap;
use alloc::vec;
use alloc::vec::Vec;
use bitmap::*;
use value_index::ValueIndex;
const STRIDE: u8 = 6;
type Entry<P> = (P, ValueIndex);
#[derive(Debug, Clone, Default)]
pub struct Poptrie<P, V>
where
P: Prefix,
{
nodes: Vec<Node>,
leaves: Vec<ValueIndex>,
values: Vec<V>,
entries: Vec<BTreeMap<PrefixId, Entry<P>>>,
}
impl<P, V> Poptrie<P, V>
where
P: Prefix,
{
pub fn new() -> Self {
let mut root_node = Node::new(
#[cfg(test)]
Vec::new(),
1,
0,
);
root_node.leaf_bitmap.set(StrideId(0));
Poptrie::<P, V> {
values: Vec::new(),
nodes: vec![root_node], entries: vec![BTreeMap::new()], leaves: vec![ValueIndex::NONE], }
}
pub fn insert(&mut self, prefix: P, mut value: V) -> Option<V> {
let key = prefix.address();
let prefix_length = prefix.prefix_length();
assert!(prefix_length <= P::ADDRESS::BITS);
let mut default_value_index = ValueIndex::NONE;
let mut offset = 0;
let mut parent_node_index = 0;
let mut parent_node = &self.nodes[parent_node_index];
while prefix_length >= offset + STRIDE {
let local_id = StrideId::from_address(key, offset, STRIDE);
let full_node_index = parent_node.get_child_index(local_id);
default_value_index = self.get_default(parent_node_index, local_id);
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.entries.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];
offset += STRIDE;
}
let remaining_length = prefix_length - offset;
let prefix_id = PrefixId::from_address(key, offset, remaining_length);
let old_value = if let Some(idx) = self.entries[parent_node_index]
.get(&prefix_id)
.and_then(|(_, v)| v.get())
{
core::mem::swap(&mut value, &mut self.values[idx]);
Some(value)
} else {
self.values.push(value);
let current_value_index =
ValueIndex::new((self.values.len() - 1) as u32);
self.entries[parent_node_index]
.insert(prefix_id, (prefix, current_value_index));
None
};
self.calculate_leaf_ranges(parent_node_index, default_value_index);
old_value
}
pub fn lookup<A: Into<P::ADDRESS>>(&self, address: A) -> Option<&V> {
let address = address.into();
let mut offset = 0;
let mut parent_node_index = 0;
let mut parent_node = &self.nodes[parent_node_index];
let mut local_id = StrideId::from_address(address, offset, STRIDE);
while parent_node.node_bitmap.contains(local_id) {
parent_node_index = parent_node.get_child_index(local_id);
parent_node = &self.nodes[parent_node_index];
offset += STRIDE;
local_id = StrideId::from_address(address, 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])
}
pub fn contains_key(&self, prefix: P) -> bool {
self.find_parent_node(prefix).is_some_and(|(parent_node, prefix_id)| {
self.entries[parent_node].contains_key(&prefix_id)
})
}
pub fn len(&self) -> usize {
self.values.len()
}
pub fn is_empty(&self) -> bool {
self.values.is_empty()
}
pub fn get(&self, prefix: P) -> Option<&V> {
let (parent_node, prefix_id) = self.find_parent_node(prefix)?;
self.entries[parent_node]
.get(&prefix_id)
.and_then(|(_, vi)| vi.get().map(|i| &self.values[i]))
}
pub fn get_mut(&mut self, prefix: P) -> Option<&mut V> {
let (parent_node, prefix_id) = self.find_parent_node(prefix)?;
self.entries[parent_node]
.get(&prefix_id)
.and_then(|(_, vi)| vi.get())
.map(|i| &mut self.values[i])
}
pub fn keys(&self) -> Keys<'_, P, V> {
Keys(self.iter())
}
pub fn values(&self) -> Values<'_, P, V> {
Values(self.iter())
}
pub fn values_mut(&mut self) -> ValuesMut<'_, P, V> {
ValuesMut(self.iter_mut())
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&P, &mut V) -> bool,
{
let to_remove: Vec<_> = self
.iter_mut()
.filter_map(|(p, v)| if !f(p, v) { Some(*p) } else { None })
.collect();
for prefix in to_remove {
self.remove(prefix);
}
}
pub fn remove(&mut self, prefix: P) -> Option<V> {
let value_index = self.remove_entry(0, prefix, 0, ValueIndex::NONE)?;
for higher_v in self
.leaves
.iter_mut()
.chain(
self.entries
.iter_mut()
.flat_map(|s| s.values_mut().map(|(_, vi)| vi)),
)
.filter(|higher_v| **higher_v > value_index)
{
higher_v.decrement();
}
Some(self.values.remove(value_index.get().unwrap()))
}
fn find_parent_node(&self, prefix: P) -> Option<(usize, PrefixId)> {
let address = prefix.address();
let prefix_length = prefix.prefix_length();
let mut offset = 0;
let mut parent_node_index = 0;
let mut parent_node = &self.nodes[parent_node_index];
while prefix_length >= offset + STRIDE {
let local_id = StrideId::from_address(address, offset, STRIDE);
if !parent_node.node_bitmap.contains(local_id) {
return None;
}
parent_node_index = parent_node.get_child_index(local_id);
parent_node = &self.nodes[parent_node_index];
offset += STRIDE;
}
let prefix_id =
PrefixId::from_address(address, offset, prefix_length - offset);
Some((parent_node_index, prefix_id))
}
fn remove_entry(
&mut self,
parent_node_index: usize,
prefix: P,
offset: u8,
default_value_index: ValueIndex,
) -> Option<ValueIndex> {
let address = prefix.address();
let prefix_length = prefix.prefix_length();
if prefix_length >= offset + STRIDE {
let local_id = StrideId::from_address(address, offset, STRIDE);
if !self.nodes[parent_node_index].node_bitmap.contains(local_id) {
return None;
}
let child_default = self.get_default(parent_node_index, local_id);
let child_index =
self.nodes[parent_node_index].get_child_index(local_id);
let value_index = self.remove_entry(
child_index,
prefix,
offset + STRIDE,
child_default,
)?;
if self.nodes[child_index].node_bitmap.is_empty()
&& self.entries[child_index].is_empty()
{
self.remove_node(child_index, parent_node_index, local_id);
}
Some(value_index)
} else {
let prefix_id =
PrefixId::from_address(address, offset, prefix_length - offset);
self.entries[parent_node_index].remove(&prefix_id).map(|(_, v)| {
self.calculate_leaf_ranges(
parent_node_index,
default_value_index,
);
v
})
}
}
fn remove_node(
&mut self,
node_index: usize,
parent_index: usize,
local_id: StrideId,
) {
let leaf_base = self.nodes[node_index].leaf_base as usize;
self.nodes[parent_index].node_bitmap.clear(local_id);
self.nodes.remove(node_index);
self.leaves.remove(leaf_base);
self.entries.remove(node_index);
for node in &mut self.nodes[node_index..] {
node.leaf_base -= 1;
}
for node in &mut self.nodes[parent_index + 1..] {
node.node_base -= 1;
}
}
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,
) {
let leaf_base = self.nodes[node_index].leaf_base as usize;
let ids = self.nodes[node_index].node_bitmap.bit_positions();
let original_defaults: Vec<_> = ids
.iter()
.map(|p| self.get_default(node_index, StrideId(*p)))
.collect();
let (new_bitmap, new_leaves) = build_leaf_ranges(
self.entries[node_index].iter().map(|(&pid, &(_, vi))| (pid, vi)),
default_value_index,
);
let old_end = if node_index < self.nodes.len() - 1 {
self.nodes[node_index + 1].leaf_base as usize
} else {
self.leaves.len()
};
let balance =
new_leaves.len() as isize - (old_end - leaf_base) as isize;
self.nodes[node_index].leaf_bitmap = new_bitmap;
self.leaves.splice(leaf_base..old_end, new_leaves);
for node in &mut self.nodes[node_index + 1..] {
node.leaf_base = (node.leaf_base as isize + balance) as u32;
}
for (i, id) in ids.iter().enumerate() {
let new_default = self.get_default(node_index, StrideId(*id));
if original_defaults[i] != new_default {
let child_index = self.nodes[node_index].node_base as usize + i;
self.calculate_leaf_ranges(child_index, new_default);
}
}
}
fn get_default(
&self,
parent_node_index: usize,
node_stride_id: StrideId,
) -> ValueIndex {
let parent_node = &self.nodes[parent_node_index];
let leaf_bitmap_index = parent_node.leaf_base
+ self.nodes[parent_node_index]
.leaf_bitmap
.leafvec_index(node_stride_id);
self.leaves[leaf_bitmap_index as usize]
}
fn build_leaf_ranges_bulk_insert(
&mut self,
node_index: usize,
default_value_index: ValueIndex,
) {
let leaf_base = self.nodes[node_index].leaf_base as usize;
let leaf_bitmap = &mut self.nodes[node_index].leaf_bitmap;
let mut entries = self.entries[node_index].iter().peekable();
let default = entries
.peek()
.take_if(|(p, _)| p.prefix_length() == 0)
.map(|(_, (_, v))| *v)
.unwrap_or(default_value_index);
self.leaves.insert(leaf_base, default);
leaf_bitmap.set(StrideId(0));
for (prefix_id, (_, value)) in entries {
let (prefix, len) = prefix_id.components();
let leaf_id = prefix_id.stride_id();
let leafvec_index = leaf_bitmap.leafvec_index(leaf_id);
let initial_value = self.leaves[leaf_base + leafvec_index as usize];
let leaf_bitmap_index =
leaf_base + leaf_bitmap.bitmap_index(leaf_id) as usize;
if !leaf_bitmap.contains(leaf_id) {
self.leaves.insert(leaf_bitmap_index, *value);
leaf_bitmap.set(leaf_id);
} else {
self.leaves[leaf_bitmap_index] = *value;
}
let next_id = StrideId((prefix + 1) << (STRIDE - len));
if next_id.0 != (1 << STRIDE) && !leaf_bitmap.contains(next_id) {
let next_bitmap_index =
leaf_base + leaf_bitmap.bitmap_index(next_id) as usize;
self.leaves.insert(next_bitmap_index, initial_value);
leaf_bitmap.set(next_id);
}
}
}
}
#[derive(Debug, Clone, Default)]
struct Node {
#[cfg(test)]
debug_prefix: Vec<StrideId>,
node_bitmap: Bitmap,
leaf_bitmap: Bitmap,
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,
}
}
#[inline(always)]
fn get_child_index(&self, local_id: StrideId) -> usize {
(self.node_base + self.node_bitmap.bitmap_index(local_id)) as usize
}
}
fn build_leaf_ranges(
entries: impl Iterator<Item = (PrefixId, ValueIndex)>,
default_value_index: ValueIndex,
) -> (Bitmap, Vec<ValueIndex>) {
let mut leaf_bitmap = Bitmap::new();
let mut entries = entries.peekable();
let default = entries
.peek()
.take_if(|(p, _)| p.prefix_length() == 0)
.map(|(_, v)| *v)
.unwrap_or(default_value_index);
let mut leaves = vec![default];
leaf_bitmap.set(StrideId(0));
for (prefix_id, value) in entries {
let (prefix, len) = prefix_id.components();
let leaf_id = prefix_id.stride_id();
let leafvec_index = leaf_bitmap.leafvec_index(leaf_id) as usize;
let initial_value = leaves[leafvec_index];
let leaf_bitmap_index = leaf_bitmap.bitmap_index(leaf_id) as usize;
if !leaf_bitmap.contains(leaf_id) {
leaves.insert(leaf_bitmap_index, value);
leaf_bitmap.set(leaf_id);
} else {
leaves[leaf_bitmap_index] = value;
}
let next_id = StrideId((prefix + 1) << (STRIDE - len));
if next_id.0 != (1 << STRIDE) && !leaf_bitmap.contains(next_id) {
let next_bitmap_index = leaf_bitmap.bitmap_index(next_id) as usize;
leaves.insert(next_bitmap_index, initial_value);
leaf_bitmap.set(next_id);
}
}
(leaf_bitmap, leaves)
}