use crate::Enr;
pub trait Filter<TVal: Eq>: FilterClone<TVal> + Send + Sync {
fn filter(
&self,
value_to_be_inserted: &TVal,
other_vals: &mut dyn Iterator<Item = &TVal>,
) -> bool;
}
pub trait FilterClone<TVal: Eq> {
fn clone_box(&self) -> Box<dyn Filter<TVal>>;
}
impl<T, TVal: Eq> FilterClone<TVal> for T
where
T: 'static + Filter<TVal> + Clone,
{
fn clone_box(&self) -> Box<dyn Filter<TVal>> {
Box::new(self.clone())
}
}
impl<TVal: Eq> Clone for Box<dyn Filter<TVal>> {
fn clone(&self) -> Box<dyn Filter<TVal>> {
self.clone_box()
}
}
const MAX_NODES_PER_SUBNET_TABLE: usize = 10;
const MAX_NODES_PER_SUBNET_BUCKET: usize = 2;
#[derive(Clone)]
pub struct IpTableFilter;
impl Filter<Enr> for IpTableFilter {
fn filter(
&self,
value_to_be_inserted: &Enr,
other_vals: &mut dyn Iterator<Item = &Enr>,
) -> bool {
ip_filter(value_to_be_inserted, other_vals, MAX_NODES_PER_SUBNET_TABLE)
}
}
#[derive(Clone)]
pub struct IpBucketFilter;
impl Filter<Enr> for IpBucketFilter {
fn filter(
&self,
value_to_be_inserted: &Enr,
other_vals: &mut dyn Iterator<Item = &Enr>,
) -> bool {
ip_filter(
value_to_be_inserted,
other_vals,
MAX_NODES_PER_SUBNET_BUCKET,
)
}
}
fn ip_filter(
value_to_be_inserted: &Enr,
other_vals: &mut dyn Iterator<Item = &Enr>,
limit: usize,
) -> bool {
if let Some(ip) = value_to_be_inserted.ip4() {
let mut count = 0;
for enr in other_vals {
if enr == value_to_be_inserted {
continue;
}
if let Some(other_ip) = enr.ip4() {
if other_ip.octets()[0..3] == ip.octets()[0..3] {
count += 1;
}
}
if count >= limit {
return false;
}
}
}
true
}