use super::{And, Invert, Or};
use crate::{
client::Reqwest,
errors::FilterError,
event::service::{service_fn, BoxCloneService},
Request,
};
use std::future::Future;
pub type BoxedCloneFilterService<Client> =
BoxCloneService<Request<Client>, (bool, Request<Client>), FilterError>;
#[allow(type_alias_bounds)]
pub type FilterResult<E: Into<anyhow::Error> = FilterError> = Result<bool, E>;
pub trait Filter<Client = Reqwest>: Clone + Send + Sync + 'static {
type Error: Into<anyhow::Error>;
fn check(
&mut self,
request: &mut Request<Client>,
) -> impl Future<Output = FilterResult<Self::Error>> + Send;
fn invert(self) -> impl Filter<Client>
where
Client: Send,
{
Invert(self)
}
fn and<F>(self, filter: F) -> impl Filter<Client>
where
F: Filter<Client>,
Client: Send,
{
And(self, filter)
}
fn or<F>(self, filter: F) -> impl Filter<Client>
where
F: Filter<Client>,
Client: Send,
{
Or(self, filter)
}
}
impl<Client, F, Fut, Err> Filter<Client> for F
where
Client: Send + Sync + 'static,
F: FnMut(&mut Request<Client>) -> Fut + Clone + Send + Sync + 'static,
Err: Into<anyhow::Error>,
Fut: Future<Output = FilterResult<Err>> + Send,
{
type Error = Err;
fn check(
&mut self,
request: &mut Request<Client>,
) -> impl Future<Output = FilterResult<Self::Error>> + Send {
self(request)
}
}
pub fn boxed_filter_factory<Client, F>(filter: F) -> BoxedCloneFilterService<Client>
where
Client: Send + Sync + 'static,
F: Filter<Client>,
{
BoxCloneService::new(service_fn(move |mut request| {
let mut filter = filter.clone();
async move {
match filter.check(&mut request).await {
Ok(result) => Ok((result, request)),
Err(err) => Err(FilterError::new(err)),
}
}
}))
}