use crate::prefix::IpPrefix;
use std::ops::{Index, IndexMut};
use std::{fmt, vec};
#[derive(Clone)]
pub(crate) struct TrieLeaves<K, V>(pub(crate) Vec<(K, V)>);
impl<K: IpPrefix, V> TrieLeaves<K, V> {
pub fn new(capacity: usize, k: K, v: V) -> Self {
let mut leaves = Vec::with_capacity(capacity);
leaves.push((k, v));
Self(leaves)
}
}
impl<K, V> TrieLeaves<K, V> {
pub fn push(&mut self, leaf: (K, V)) -> LeafIndex {
let index = self.0.len().into();
self.0.push(leaf);
index
}
pub fn remove_last(&mut self) -> Option<(K, V)> {
debug_assert!(self.0.len() > 1);
self.0.pop()
}
#[allow(dead_code)]
pub fn remove(&mut self, i: LeafIndex) -> (K, V) {
debug_assert!(!i.is_root_leaf());
self.0.swap_remove(i.index())
}
pub fn len(&self) -> usize {
self.0.len()
}
}
impl<K, V> Index<LeafIndex> for TrieLeaves<K, V> {
type Output = (K, V);
fn index(&self, i: LeafIndex) -> &Self::Output {
debug_assert!(i.index() < self.0.len());
unsafe { self.0.get_unchecked(i.index()) }
}
}
impl<K, V> IndexMut<LeafIndex> for TrieLeaves<K, V> {
fn index_mut(&mut self, i: LeafIndex) -> &mut Self::Output {
debug_assert!(i.index() < self.0.len());
unsafe { self.0.get_unchecked_mut(i.index()) }
}
}
impl<K, V> IntoIterator for TrieLeaves<K, V> {
type Item = (K, V);
type IntoIter = vec::IntoIter<(K, V)>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
pub static INDEX_MAX: usize = i32::MAX as usize;
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub(crate) struct NodeIndex(pub(crate) i32);
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub(crate) struct LeafIndex(i32);
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub(crate) struct BranchingIndex(i32);
#[allow(dead_code)]
impl NodeIndex {
#[inline]
pub(crate) fn root() -> Self {
Self(0)
}
#[inline]
pub(crate) fn root_leaf() -> Self {
Self(!0)
}
#[inline]
pub(crate) fn is_root(&self) -> bool {
self.0 == 0
}
#[inline]
pub(crate) fn is_branching(&self) -> bool {
self.0 >= 0
}
#[inline]
pub(crate) fn is_leaf(&self) -> bool {
self.0 < 0
}
#[inline]
pub(crate) fn as_leaf(&self) -> LeafIndex {
(*self).into()
}
#[inline]
pub(crate) fn as_branching(&self) -> BranchingIndex {
(*self).into()
}
}
impl LeafIndex {
#[inline]
pub(crate) fn root_leaf() -> Self {
Self(0)
}
#[inline]
pub(crate) fn is_root_leaf(&self) -> bool {
self.0 == 0
}
#[inline]
pub(crate) fn index(&self) -> usize {
self.0 as usize
}
}
impl BranchingIndex {
#[inline]
pub(crate) fn root() -> Self {
Self(0)
}
#[inline]
pub(crate) fn is_root(&self) -> bool {
self.0 == 0
}
#[inline]
pub(crate) fn index(&self) -> usize {
self.0 as usize
}
}
impl From<NodeIndex> for LeafIndex {
#[inline]
fn from(i: NodeIndex) -> Self {
debug_assert!(i.is_leaf());
Self(!i.0)
}
}
impl From<usize> for LeafIndex {
#[inline]
fn from(i: usize) -> Self {
debug_assert!(i <= INDEX_MAX);
Self(i as i32)
}
}
impl From<usize> for BranchingIndex {
#[inline]
fn from(i: usize) -> Self {
debug_assert!(i <= INDEX_MAX);
Self(i as i32)
}
}
impl From<NodeIndex> for BranchingIndex {
#[inline]
fn from(i: NodeIndex) -> Self {
debug_assert!(i.is_branching());
Self(i.0)
}
}
impl From<LeafIndex> for NodeIndex {
#[inline]
fn from(i: LeafIndex) -> Self {
Self(!i.0)
}
}
impl From<BranchingIndex> for NodeIndex {
#[inline]
fn from(i: BranchingIndex) -> Self {
Self(i.0)
}
}
impl PartialEq<LeafIndex> for NodeIndex {
#[inline]
fn eq(&self, other: &LeafIndex) -> bool {
self.0 == !other.0
}
}
impl PartialEq<BranchingIndex> for NodeIndex {
#[inline]
fn eq(&self, other: &BranchingIndex) -> bool {
self.0 == other.0
}
}
impl PartialEq<NodeIndex> for BranchingIndex {
#[inline]
fn eq(&self, other: &NodeIndex) -> bool {
self.0 == other.0
}
}
impl PartialEq<NodeIndex> for LeafIndex {
#[inline]
fn eq(&self, other: &NodeIndex) -> bool {
self.0 == !other.0
}
}
impl fmt::Debug for LeafIndex {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&(!self.0), f)
}
}
impl fmt::Debug for BranchingIndex {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl fmt::Debug for NodeIndex {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}