use core::marker::PhantomData;
use alloc::collections::btree_map::BTreeMap;
use crate::key::{Key, extract_bits, extract_bits_saturated};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct Bitmap<T>
where
T: Copy + Into<u8>,
{
bits: u64,
_phantom: PhantomData<T>,
}
impl<T> Bitmap<T>
where
T: Copy + Into<u8>,
{
#[inline(always)]
pub(crate) fn new() -> Self {
Bitmap { bits: 0u64, _phantom: PhantomData }
}
#[inline(always)] pub(crate) fn bitmap_index(&self, id: T) -> u32 {
if id.into() == 0 {
0
} else {
(self.bits << (64u8 - id.into())).count_ones()
}
}
#[inline(always)] pub(crate) fn leafvec_index(&self, id: T) -> u32 {
(self.bits << (63u8 - id.into())).count_ones() - 1
}
#[inline(always)]
pub(crate) fn contains(&self, id: T) -> bool {
self.bits & (1 << id.into()) != 0
}
#[inline(always)]
pub(crate) fn set(&mut self, id: T) {
self.bits |= 1 << id.into();
}
#[inline(always)]
pub(crate) fn pop_count(&self) -> u32 {
self.bits.count_ones()
}
}
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub(crate) struct PrefixId(u8);
impl PrefixId {
pub(crate) fn new(prefix: u8, len: u8) -> Self {
PrefixId((1u8 << len) - 1 + prefix)
}
pub(crate) fn from_key<K: Key>(key: K, key_offset: u8, stride: u8) -> Self {
let prefix = extract_bits_saturated(key, key_offset, stride);
PrefixId::new(prefix, stride)
}
pub(crate) fn parent(&self) -> Self {
PrefixId((self.0 - 1) >> 1)
}
}
#[inline(always)]
pub(crate) fn find_leaf_lpm<T>(
tree: &BTreeMap<PrefixId, T>,
mut local_id: PrefixId,
) -> Option<T>
where
T: Copy,
{
while !tree.contains_key(&local_id) {
if local_id.0 == 0 {
return None;
}
local_id = local_id.parent();
}
Some(tree[&local_id])
}
#[repr(transparent)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct StrideId(pub(crate) u8);
impl StrideId {
pub(crate) fn from_key<K: Key>(
key: K,
key_offset: u8,
length: u8,
) -> StrideId {
StrideId(extract_bits(key, key_offset, length))
}
}
impl Into<u8> for StrideId {
fn into(self) -> u8 {
self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bitmap_index_test() {
let mut bitmap = Bitmap::<u8>::new();
assert_eq!(bitmap.bitmap_index(0), 0);
assert_eq!(bitmap.bitmap_index(63), 0);
bitmap.set(1);
assert_eq!(bitmap.bitmap_index(1), 0);
assert_eq!(bitmap.bitmap_index(2), 1);
assert_eq!(bitmap.bitmap_index(63), 1);
let mut thirty_two = Bitmap::<u8>::new();
thirty_two.set(5);
assert_eq!(thirty_two.bitmap_index(5), 0);
assert_eq!(thirty_two.bitmap_index(6), 1);
assert_eq!(thirty_two.bitmap_index(63), 1);
let mut full = Bitmap::<u8>::new();
full.bits = u64::MAX;
assert_eq!(full.bitmap_index(63), 63);
}
#[test]
fn bitmap_id_prefix_test() {
assert_eq!(PrefixId::new(0, 0), PrefixId(0));
assert_eq!(PrefixId::new(0, 1), PrefixId(1));
assert_eq!(PrefixId::new(1, 1), PrefixId(2));
}
#[test]
fn test_find_lpm() {
let mut tree = BTreeMap::<PrefixId, u32>::new();
tree.insert(PrefixId::new(1, 1), 1);
assert_eq!(find_leaf_lpm(&tree, PrefixId::new(1, 1)), Some(1));
assert_eq!(find_leaf_lpm(&tree, PrefixId::new(2, 2)), Some(1));
assert_eq!(find_leaf_lpm(&tree, PrefixId::new(3, 2)), Some(1));
assert_eq!(find_leaf_lpm(&tree, PrefixId::new(4, 3)), Some(1));
tree.insert(PrefixId::new(2, 2), 2);
assert_eq!(find_leaf_lpm(&tree, PrefixId::new(2, 2)), Some(2));
assert_eq!(find_leaf_lpm(&tree, PrefixId::new(4, 3)), Some(2));
assert_eq!(find_leaf_lpm(&tree, PrefixId::new(1, 1)), Some(1));
assert_eq!(find_leaf_lpm(&tree, PrefixId::new(3, 2)), Some(1));
assert_eq!(find_leaf_lpm(&tree, PrefixId::new(0, 1)), None);
}
}