use dyn_clone::DynClone;
use crate::{circuit::metadata::MetaItem, dynamic::Factory};
pub trait FilterFunc<V: ?Sized>: Fn(&V) -> bool + DynClone + Send + Sync {}
impl<V: ?Sized, F> FilterFunc<V> for F where F: Fn(&V) -> bool + Clone + Send + Sync + 'static {}
dyn_clone::clone_trait_object! {<V: ?Sized> FilterFunc<V>}
pub struct Filter<V: ?Sized> {
filter_func: Box<dyn FilterFunc<V>>,
metadata: MetaItem,
}
impl<V: ?Sized> Filter<V> {
pub fn new(filter_func: Box<dyn FilterFunc<V>>) -> Self {
Self {
filter_func,
metadata: MetaItem::String(String::new()),
}
}
pub fn with_metadata(mut self, metadata: MetaItem) -> Self {
self.metadata = metadata;
self
}
pub fn filter_func(&self) -> &dyn FilterFunc<V> {
self.filter_func.as_ref()
}
pub fn metadata(&self) -> &MetaItem {
&self.metadata
}
pub fn include(this: &Option<Filter<V>>, value: &V) -> bool {
this.as_ref().is_none_or(|f| (f.filter_func)(value))
}
}
impl<V: ?Sized> Clone for Filter<V> {
fn clone(&self) -> Self {
Self {
filter_func: self.filter_func.clone(),
metadata: self.metadata.clone(),
}
}
}
pub enum GroupFilter<V: ?Sized + 'static> {
Simple(Filter<V>),
LastN(usize, Filter<V>),
TopN(usize, Filter<V>, &'static dyn Factory<V>),
BottomN(usize, Filter<V>, &'static dyn Factory<V>),
}
impl<V: ?Sized + 'static> GroupFilter<V> {
pub fn requires_snapshot(&self) -> bool {
match self {
Self::Simple(..) => false,
Self::LastN(..) => true,
Self::TopN(..) => true,
Self::BottomN(..) => true,
}
}
}
impl<V: ?Sized> Clone for GroupFilter<V> {
fn clone(&self) -> Self {
match self {
Self::Simple(filter) => Self::Simple(filter.clone()),
Self::LastN(n, filter) => Self::LastN(*n, filter.clone()),
Self::TopN(n, filter, vals_factory) => Self::TopN(*n, filter.clone(), *vals_factory),
Self::BottomN(n, filter, vals_factory) => {
Self::BottomN(*n, filter.clone(), *vals_factory)
}
}
}
}
impl<V: ?Sized> GroupFilter<V> {
pub fn metadata(&self) -> MetaItem {
match self {
Self::Simple(filter) => filter.metadata().clone(),
Self::LastN(_n, filter) => filter.metadata().clone(),
Self::TopN(_n, filter, _vals_factory) => filter.metadata().clone(),
Self::BottomN(_n, filter, _vals_factory) => filter.metadata().clone(),
}
}
}