use std::{future::Future, sync::Arc};
pub trait Predicate<Request> {
type Request;
type Response;
fn check(&self, request: Request) -> Result<Self::Request, Self::Response>;
}
impl<T, Req, Res, F> Predicate<T> for F
where
F: Fn(T) -> Result<Req, Res>,
{
type Request = Req;
type Response = Res;
fn check(&self, request: T) -> Result<Self::Request, Self::Response> {
self(request)
}
}
pub trait AsyncPredicate<R> {
type Request;
type Response;
type Future: Future<Output = Result<Self::Request, Self::Response>>;
fn check(&self, request: R) -> Self::Future;
}
impl<T, Req, Res, U, F> AsyncPredicate<T> for F
where
F: Fn(T) -> U,
U: Future<Output = Result<Req, Res>>,
{
type Request = Req;
type Response = Res;
type Future = U;
fn check(&self, request: T) -> Self::Future {
self(request)
}
}
impl<T, R> AsyncPredicate<R> for Arc<T>
where
T: AsyncPredicate<R>,
{
type Request = T::Request;
type Response = T::Response;
type Future = T::Future;
fn check(&self, request: R) -> Self::Future {
(**self).check(request)
}
}