#[cfg(test)]
#[cfg(feature = "ipnet")]
mod test;
mod difference;
mod intersection;
mod union;
use std::num::NonZeroUsize;
pub use difference::{
CoveringDifference, CoveringDifferenceMut, Difference, DifferenceItem, DifferenceMut,
DifferenceMutItem,
};
pub use intersection::{Intersection, IntersectionMut};
pub use union::{Union, UnionItem, UnionMut};
use crate::{
inner::{Direction, DirectionForInsert, Node, Table},
map::{Iter, IterMut, Keys, Values, ValuesMut},
to_right, Prefix, PrefixMap, PrefixSet,
};
pub trait AsView: Sized {
type P: Prefix;
type T;
fn view(&self) -> TrieView<'_, Self::P, Self::T>;
fn view_at(&self, prefix: Self::P) -> Option<TrieView<'_, Self::P, Self::T>> {
self.view().find(prefix)
}
}
impl<'a, P: Prefix + Clone, T> AsView for TrieView<'a, P, T> {
type P = P;
type T = T;
fn view(&self) -> TrieView<'a, P, T> {
self.clone()
}
}
impl<'a, P: Prefix + Clone, T> AsView for &TrieView<'a, P, T> {
type P = P;
type T = T;
fn view(&self) -> TrieView<'a, P, T> {
(*self).clone()
}
}
impl<P: Prefix + Clone, T> AsView for TrieViewMut<'_, P, T> {
type P = P;
type T = T;
fn view(&self) -> TrieView<'_, P, T> {
TrieView {
table: self.table,
loc: self.loc.clone(),
}
}
}
impl<P: Prefix, T> AsView for PrefixMap<P, T> {
type P = P;
type T = T;
fn view(&self) -> TrieView<'_, P, T> {
TrieView {
table: &self.table,
loc: ViewLoc::Node(0),
}
}
}
impl<P: Prefix> AsView for PrefixSet<P> {
type P = P;
type T = ();
fn view(&self) -> TrieView<'_, P, ()> {
TrieView {
table: &self.0.table,
loc: ViewLoc::Node(0),
}
}
}
pub struct TrieView<'a, P, T> {
table: &'a Table<P, T>,
loc: ViewLoc<P>,
}
#[derive(Clone, Copy)]
enum ViewLoc<P> {
Node(usize),
Virtual(P, NonZeroUsize),
}
impl<P> ViewLoc<P> {
fn idx(&self) -> usize {
match self {
ViewLoc::Node(i) => *i,
ViewLoc::Virtual(_, i) => i.get(),
}
}
}
impl<P: Copy, T> Copy for TrieView<'_, P, T> {}
impl<P: Clone, T> Clone for TrieView<'_, P, T> {
fn clone(&self) -> Self {
Self {
table: self.table,
loc: self.loc.clone(),
}
}
}
impl<P: std::fmt::Debug, T: std::fmt::Debug> std::fmt::Debug for TrieView<'_, P, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("View").field(self.prefix()).finish()
}
}
impl<P, L, Rhs> PartialEq<Rhs> for TrieView<'_, P, L>
where
P: Prefix + PartialEq,
L: PartialEq<Rhs::T>,
Rhs: crate::AsView<P = P>,
{
fn eq(&self, other: &Rhs) -> bool {
self.iter()
.zip(other.view().iter())
.all(|((lp, lt), (rp, rt))| lt == rt && lp == rp)
}
}
impl<P, T> Eq for TrieView<'_, P, T>
where
P: Prefix + Eq + Clone,
T: Eq,
{
}
impl<'a, P, T> TrieView<'a, P, T>
where
P: Prefix,
{
pub fn find(&self, prefix: P) -> Option<TrieView<'a, P, T>> {
let mut idx = self.loc.idx();
loop {
match self.table.get_direction_for_insert(idx, &prefix) {
DirectionForInsert::Enter { next, .. } => {
idx = next;
}
DirectionForInsert::Reached => {
return Some(Self {
table: self.table,
loc: ViewLoc::Node(idx),
});
}
DirectionForInsert::NewChild { right, .. } => {
return Some(Self {
table: self.table,
loc: ViewLoc::Virtual(prefix, self.table.get_child(idx, right).unwrap()),
});
}
DirectionForInsert::NewLeaf { .. } | DirectionForInsert::NewBranch { .. } => {
return None;
}
}
}
}
pub fn find_exact(&self, prefix: &P) -> Option<TrieView<'a, P, T>> {
let mut idx = self.loc.idx();
loop {
match self.table.get_direction(idx, prefix) {
Direction::Reached => {
return self.table[idx].value.is_some().then_some(Self {
table: self.table,
loc: ViewLoc::Node(idx),
});
}
Direction::Enter { next, .. } => idx = next.get(),
Direction::Missing => return None,
}
}
}
pub fn find_lpm(&self, prefix: &P) -> Option<TrieView<'a, P, T>> {
let mut idx = self.loc.idx();
let mut best_match = None;
loop {
if self.table[idx].value.is_some() {
best_match = Some(idx);
}
match self.table.get_direction(idx, prefix) {
Direction::Enter { next, .. } => idx = next.get(),
_ => {
return best_match.map(|idx| Self {
table: self.table,
loc: ViewLoc::Node(idx),
});
}
}
}
}
pub fn left(&self) -> Option<Self> {
match &self.loc {
ViewLoc::Node(idx) => Some(Self {
table: self.table,
loc: ViewLoc::Node(self.table[*idx].left?.get()),
}),
ViewLoc::Virtual(p, idx) => {
if !to_right(p, &self.table[*idx].prefix) {
Some(Self {
table: self.table,
loc: ViewLoc::Node(idx.get()),
})
} else {
None
}
}
}
}
pub fn right(&self) -> Option<Self> {
match &self.loc {
ViewLoc::Node(idx) => Some(Self {
table: self.table,
loc: ViewLoc::Node(self.table[*idx].right?.get()),
}),
ViewLoc::Virtual(p, idx) => {
if to_right(p, &self.table[*idx].prefix) {
Some(Self {
table: self.table,
loc: ViewLoc::Node(idx.get()),
})
} else {
None
}
}
}
}
}
impl<'a, P, T> TrieView<'a, P, T> {
pub fn iter(&self) -> Iter<'a, P, T> {
Iter::new(self.table, vec![self.loc.idx()])
}
pub fn keys(&self) -> Keys<'a, P, T> {
Keys { inner: self.iter() }
}
pub fn values(&self) -> Values<'a, P, T> {
Values { inner: self.iter() }
}
pub fn prefix(&self) -> &P {
match &self.loc {
ViewLoc::Node(idx) => &self.table[*idx].prefix,
ViewLoc::Virtual(p, _) => p,
}
}
pub fn value(&self) -> Option<&'a T> {
match &self.loc {
ViewLoc::Node(idx) => self.table[*idx].value.as_ref(),
ViewLoc::Virtual(_, _) => None,
}
}
pub fn prefix_value(&self) -> Option<(&'a P, &'a T)> {
match &self.loc {
ViewLoc::Node(idx) => self.table[*idx].prefix_value(),
ViewLoc::Virtual(_, _) => None,
}
}
}
impl<'a, P, T> IntoIterator for TrieView<'a, P, T> {
type Item = (&'a P, &'a T);
type IntoIter = Iter<'a, P, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
pub trait AsViewMut<'a, P: Prefix, T>: Sized {
fn view_mut(self) -> TrieViewMut<'a, P, T>;
fn view_mut_at(self, prefix: P) -> Option<TrieViewMut<'a, P, T>> {
self.view_mut().find(prefix).ok()
}
}
impl<'a, P: Prefix, T> AsViewMut<'a, P, T> for TrieViewMut<'a, P, T> {
fn view_mut(self) -> TrieViewMut<'a, P, T> {
self
}
}
impl<'a, P: Prefix, T> AsViewMut<'a, P, T> for &'a mut PrefixMap<P, T> {
fn view_mut(self) -> TrieViewMut<'a, P, T> {
unsafe { TrieViewMut::new(&self.table, ViewLoc::Node(0)) }
}
}
impl<'a, P: Prefix> AsViewMut<'a, P, ()> for &'a mut PrefixSet<P> {
fn view_mut(self) -> TrieViewMut<'a, P, ()> {
self.0.view_mut()
}
}
pub struct TrieViewMut<'a, P, T> {
table: &'a Table<P, T>,
loc: ViewLoc<P>,
}
impl<'a, P, T> TrieViewMut<'a, P, T> {
unsafe fn new(table: &'a Table<P, T>, loc: ViewLoc<P>) -> Self {
Self { table, loc }
}
}
impl<P: std::fmt::Debug, T: std::fmt::Debug> std::fmt::Debug for TrieViewMut<'_, P, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("ViewMut").field(self.prefix()).finish()
}
}
impl<P, L, Rhs> PartialEq<Rhs> for TrieViewMut<'_, P, L>
where
P: Prefix + PartialEq + Clone,
L: PartialEq<Rhs::T>,
Rhs: crate::AsView<P = P>,
{
fn eq(&self, other: &Rhs) -> bool {
self.view()
.iter()
.zip(other.view().iter())
.all(|((lp, lt), (rp, rt))| lt == rt && lp == rp)
}
}
impl<P, T> Eq for TrieViewMut<'_, P, T>
where
P: Prefix + Eq + Clone,
T: Eq,
{
}
impl<P, T> TrieViewMut<'_, P, T>
where
P: Prefix,
{
pub fn find(self, prefix: P) -> Result<Self, Self> {
let mut idx = self.loc.idx();
loop {
match self.table.get_direction_for_insert(idx, &prefix) {
DirectionForInsert::Enter { next, .. } => {
idx = next;
}
DirectionForInsert::Reached => {
let new_loc = ViewLoc::Node(idx);
return unsafe { Ok(Self::new(self.table, new_loc)) };
}
DirectionForInsert::NewChild { right, .. } => {
let new_loc =
ViewLoc::Virtual(prefix, self.table.get_child(idx, right).unwrap());
return unsafe { Ok(Self::new(self.table, new_loc)) };
}
DirectionForInsert::NewLeaf { .. } | DirectionForInsert::NewBranch { .. } => {
return Err(self);
}
}
}
}
pub fn find_exact(self, prefix: &P) -> Result<Self, Self> {
let mut idx = self.loc.idx();
loop {
match self.table.get_direction(idx, prefix) {
Direction::Reached => {
return if self.table[idx].value.is_some() {
unsafe { Ok(Self::new(self.table, ViewLoc::Node(idx))) }
} else {
Err(self)
};
}
Direction::Enter { next, .. } => idx = next.get(),
Direction::Missing => return Err(self),
}
}
}
pub fn find_lpm(self, prefix: &P) -> Result<Self, Self> {
let mut idx = self.loc.idx();
let mut best_match = None;
loop {
if self.table[idx].value.is_some() {
best_match = Some(idx);
}
match self.table.get_direction(idx, prefix) {
Direction::Enter { next, .. } => idx = next.get(),
_ => {
return if let Some(idx) = best_match {
unsafe { Ok(Self::new(self.table, ViewLoc::Node(idx))) }
} else {
Err(self)
};
}
}
}
}
pub fn left(self) -> Result<Self, Self> {
let left_idx = match &self.loc {
ViewLoc::Node(idx) => self.table[*idx].left,
ViewLoc::Virtual(p, idx) => {
if !to_right(p, &self.table[*idx].prefix) {
Some(*idx)
} else {
None
}
}
};
if let Some(idx) = left_idx {
unsafe { Ok(Self::new(self.table, ViewLoc::Node(idx.get()))) }
} else {
Err(self)
}
}
pub fn right(self) -> Result<Self, Self> {
let right_idx = match &self.loc {
ViewLoc::Node(idx) => self.table[*idx].right,
ViewLoc::Virtual(p, idx) => {
if to_right(p, &self.table[*idx].prefix) {
Some(*idx)
} else {
None
}
}
};
if let Some(idx) = right_idx {
unsafe { Ok(Self::new(self.table, ViewLoc::Node(idx.get()))) }
} else {
Err(self)
}
}
pub fn has_left(&self) -> bool {
match &self.loc {
ViewLoc::Node(idx) => self.table[*idx].left.is_some(),
ViewLoc::Virtual(p, idx) => {
!to_right(p, &self.table[*idx].prefix)
}
}
}
pub fn has_right(&self) -> bool {
match &self.loc {
ViewLoc::Node(idx) => self.table[*idx].right.is_some(),
ViewLoc::Virtual(p, idx) => {
to_right(p, &self.table[*idx].prefix)
}
}
}
pub fn split(self) -> (Option<Self>, Option<Self>) {
let (left, right) = match &self.loc {
ViewLoc::Node(idx) => (self.table[*idx].left, self.table[*idx].right),
ViewLoc::Virtual(p, idx) => {
if to_right(p, &self.table[*idx].prefix) {
(None, Some(*idx))
} else {
(Some(*idx), None)
}
}
};
unsafe {
(
left.map(|idx| Self::new(self.table, ViewLoc::Node(idx.get()))),
right.map(|idx| Self::new(self.table, ViewLoc::Node(idx.get()))),
)
}
}
}
impl<P, T> TrieViewMut<'_, P, T> {
pub fn iter_mut(&mut self) -> IterMut<'_, P, T> {
unsafe { IterMut::new(self.table, vec![self.loc.idx()]) }
}
pub fn values_mut(&mut self) -> ValuesMut<'_, P, T> {
ValuesMut {
inner: self.iter_mut(),
}
}
pub fn prefix(&self) -> &P {
match &self.loc {
ViewLoc::Node(idx) => &self.table[*idx].prefix,
ViewLoc::Virtual(p, _) => p,
}
}
pub fn value(&self) -> Option<&T> {
match &self.loc {
ViewLoc::Node(idx) => self.table[*idx].value.as_ref(),
ViewLoc::Virtual(_, _) => None,
}
}
fn node_mut(&mut self) -> Option<&mut Node<P, T>> {
match &self.loc {
ViewLoc::Node(idx) => unsafe { Some(self.table.get_mut(*idx)) },
ViewLoc::Virtual(_, _) => None,
}
}
pub fn value_mut(&mut self) -> Option<&mut T> {
self.node_mut()?.value.as_mut()
}
pub fn prefix_value(&self) -> Option<(&P, &T)> {
match &self.loc {
ViewLoc::Node(idx) => self.table[*idx].prefix_value(),
ViewLoc::Virtual(_, _) => None,
}
}
pub fn prefix_value_mut(&mut self) -> Option<(&P, &mut T)> {
self.node_mut()?.prefix_value_mut()
}
pub fn remove(&mut self) -> Option<T> {
self.node_mut()?.value.take()
}
pub fn set(&mut self, value: T) -> Result<Option<T>, T> {
match self.node_mut() {
Some(n) => Ok(n.value.replace(value)),
None => Err(value),
}
}
}
impl<'a, P, T> IntoIterator for TrieViewMut<'a, P, T> {
type Item = (&'a P, &'a mut T);
type IntoIter = IterMut<'a, P, T>;
fn into_iter(self) -> Self::IntoIter {
unsafe { IterMut::new(self.table, vec![self.loc.idx()]) }
}
}