use crate::HandlerDescription;
use std::{
collections::HashSet,
hash::{BuildHasher, Hash, RandomState},
};
#[derive(Debug, Clone)]
pub struct InterestSet<K, S = RandomState> {
pub observed: HashSet<K, S>,
pub filtered: HashSet<K, S>,
}
pub trait EventKind<S = RandomState>: Sized {
fn full_set() -> HashSet<Self, S>;
fn empty_set() -> HashSet<Self, S>;
}
impl<K: EventKind<S>, S> InterestSet<K, S> {
pub fn new_filter(filtered: HashSet<K, S>) -> Self {
Self { observed: K::empty_set(), filtered }
}
}
impl<T, S> HandlerDescription for InterestSet<T, S>
where
T: EventKind<S> + Eq + Hash + Clone,
S: BuildHasher + Clone,
T: Send + Sync + 'static,
S: Send + Sync + 'static,
{
fn entry() -> Self {
Self { observed: T::empty_set(), filtered: T::full_set() }
}
fn user_defined() -> Self {
Self { observed: T::full_set(), filtered: T::full_set() }
}
fn endpoint() -> Self {
Self { observed: T::full_set(), filtered: T::empty_set() }
}
fn merge_chain(&self, other: &Self) -> Self {
let Self { observed: l_obs, filtered: l_flt } = self;
let Self { observed: r_obs, filtered: r_flt } = other;
let observed = {
let hasher = l_obs.hasher().clone();
let mut tmp = HashSet::with_hasher(hasher);
tmp.extend(l_obs.iter().cloned());
tmp.extend(l_flt.intersection(r_obs).cloned());
tmp
};
let filtered = {
let hasher = l_flt.hasher().clone();
let mut tmp = HashSet::with_hasher(hasher);
tmp.extend(l_flt.intersection(r_flt).cloned());
tmp
};
Self { filtered, observed }
}
fn merge_branch(&self, other: &Self) -> Self {
let Self { observed: l_obs, filtered: l_flt } = self;
let Self { observed: r_obs, filtered: _ } = other;
let observed = {
let hasher = l_obs.hasher().clone();
let mut tmp = HashSet::with_hasher(hasher);
tmp.extend(l_obs.iter().cloned());
tmp.extend(l_flt.intersection(r_obs).cloned());
tmp
};
let filtered = l_flt.clone();
Self { observed, filtered }
}
}
impl<K: Hash + Eq, S: BuildHasher> Eq for InterestSet<K, S> {}
impl<K: Hash + Eq, S: BuildHasher> PartialEq for InterestSet<K, S> {
fn eq(&self, other: &Self) -> bool {
let Self { observed: l_obs, filtered: l_flt } = self;
let Self { observed: r_obs, filtered: r_flt } = other;
l_obs == r_obs && l_flt == r_flt
}
}