use core::net::IpAddr;
mod simple;
mod split_stack;
pub use simple::SimpleTable;
pub use split_stack::SplitStackTable;
use crate::RouteModification;
pub type DynModifyFn<'a, T> = &'a mut dyn FnMut(Option<&mut T>) -> RouteModification<T>;
pub trait RoutingTable {
type Value: 'static;
fn contains(&self, ip: IpAddr) -> bool;
fn insert(&mut self, prefix: ipnet::IpNet, val: Self::Value) -> Option<Self::Value>;
fn remove(&mut self, prefix: ipnet::IpNet) -> Option<Self::Value>;
fn clear(&mut self);
#[doc(hidden)]
fn modify_impl(
&mut self,
prefix: ipnet::IpNet,
modify: DynModifyFn<Self::Value>,
) -> Option<Self::Value>;
fn lookup(&self, ip: IpAddr) -> Option<&Self::Value>;
fn lookup_all(&self, ip: IpAddr) -> crate::iptrie::LookupIter<'_, Self::Value>;
fn lookup_prefix_exact(&self, prefix: ipnet::IpNet) -> Option<&Self::Value>;
fn lookup_prefix(&self, prefix: ipnet::IpNet) -> Option<&Self::Value>;
fn lookup_prefix_lpm(&self, prefix: ipnet::IpNet) -> Option<(ipnet::IpNet, &Self::Value)>;
fn size(&self) -> usize;
}
static_assertions::assert_obj_safe!(RoutingTable<Value = ()>);
impl<T> RoutingTable for &mut T
where
T: RoutingTable,
{
type Value = T::Value;
fn insert(&mut self, prefix: ipnet::IpNet, val: Self::Value) -> Option<Self::Value> {
(*self).insert(prefix, val)
}
fn remove(&mut self, prefix: ipnet::IpNet) -> Option<Self::Value> {
(*self).remove(prefix)
}
fn clear(&mut self) {
(*self).clear()
}
fn modify_impl(
&mut self,
prefix: ipnet::IpNet,
modify: DynModifyFn<Self::Value>,
) -> Option<Self::Value> {
(*self).modify_impl(prefix, modify)
}
fn contains(&self, ip: IpAddr) -> bool {
(**self).contains(ip)
}
fn lookup(&self, ip: IpAddr) -> Option<&Self::Value> {
(**self).lookup(ip)
}
fn lookup_all(&self, ip: IpAddr) -> crate::iptrie::LookupIter<'_, Self::Value> {
(**self).lookup_all(ip)
}
fn lookup_prefix_exact(&self, prefix: ipnet::IpNet) -> Option<&Self::Value> {
(**self).lookup_prefix_exact(prefix)
}
fn lookup_prefix(&self, prefix: ipnet::IpNet) -> Option<&Self::Value> {
(**self).lookup_prefix(prefix)
}
fn lookup_prefix_lpm(&self, prefix: ipnet::IpNet) -> Option<(ipnet::IpNet, &Self::Value)> {
(**self).lookup_prefix_lpm(prefix)
}
fn size(&self) -> usize {
(**self).size()
}
}
mod private {
pub trait Sealed {}
}
pub trait RoutingTableExt: RoutingTable + private::Sealed {
#[inline]
fn modify(
&mut self,
prefix: ipnet::IpNet,
modify: impl FnOnce(Option<&mut Self::Value>) -> RouteModification<Self::Value>,
) -> Option<Self::Value> {
let mut modify = Some(modify);
self.modify_impl(prefix, &mut move |val| {
modify
.take()
.expect("modify implementation called closure more than once")(val)
})
}
}
impl<T> private::Sealed for T where T: RoutingTable {}
impl<T> RoutingTableExt for T where T: RoutingTable {}