pub mod future;
mod layer;
mod predicate;
pub use self::{
layer::{AsyncFilterLayer, FilterLayer},
predicate::{AsyncPredicate, Predicate},
};
use self::future::{AsyncResponseFuture, ResponseFuture};
use crate::BoxError;
use futures_util::{future::Either, TryFutureExt};
use std::task::{Context, Poll};
use tower_service::Service;
#[derive(Clone, Debug)]
pub struct Filter<T, U> {
inner: T,
predicate: U,
}
#[derive(Clone, Debug)]
pub struct AsyncFilter<T, U> {
inner: T,
predicate: U,
}
impl<T, U> Filter<T, U> {
pub const fn new(inner: T, predicate: U) -> Self {
Self { inner, predicate }
}
pub fn layer(predicate: U) -> FilterLayer<U> {
FilterLayer::new(predicate)
}
pub fn check<R>(&mut self, request: R) -> Result<U::Request, BoxError>
where
U: Predicate<R>,
{
self.predicate.check(request)
}
pub fn get_ref(&self) -> &T {
&self.inner
}
pub fn get_mut(&mut self) -> &mut T {
&mut self.inner
}
pub fn into_inner(self) -> T {
self.inner
}
}
impl<T, U, Request> Service<Request> for Filter<T, U>
where
U: Predicate<Request>,
T: Service<U::Request>,
T::Error: Into<BoxError>,
{
type Response = T::Response;
type Error = BoxError;
type Future = ResponseFuture<T::Response, T::Future>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx).map_err(Into::into)
}
fn call(&mut self, request: Request) -> Self::Future {
ResponseFuture::new(match self.predicate.check(request) {
Ok(request) => Either::Right(self.inner.call(request).err_into()),
Err(e) => Either::Left(futures_util::future::ready(Err(e))),
})
}
}
impl<T, U> AsyncFilter<T, U> {
pub const fn new(inner: T, predicate: U) -> Self {
Self { inner, predicate }
}
pub fn layer(predicate: U) -> FilterLayer<U> {
FilterLayer::new(predicate)
}
pub async fn check<R>(&mut self, request: R) -> Result<U::Request, BoxError>
where
U: AsyncPredicate<R>,
{
self.predicate.check(request).await
}
pub fn get_ref(&self) -> &T {
&self.inner
}
pub fn get_mut(&mut self) -> &mut T {
&mut self.inner
}
pub fn into_inner(self) -> T {
self.inner
}
}
impl<T, U, Request> Service<Request> for AsyncFilter<T, U>
where
U: AsyncPredicate<Request>,
T: Service<U::Request> + Clone,
T::Error: Into<BoxError>,
{
type Response = T::Response;
type Error = BoxError;
type Future = AsyncResponseFuture<U, T, Request>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx).map_err(Into::into)
}
fn call(&mut self, request: Request) -> Self::Future {
use std::mem;
let inner = self.inner.clone();
let inner = mem::replace(&mut self.inner, inner);
let check = self.predicate.check(request);
AsyncResponseFuture::new(check, inner)
}
}