mod project;
use std::marker::PhantomData;
use http::HeaderName;
pub use project::*;
use super::Predicate;
use super::error::OnError;
pub struct On<T, U> {
predicate: T,
projector: U,
}
pub struct Opt<T, U> {
predicate: T,
projector: U,
}
pub fn on<T, U>(predicate: T, projector: U) -> On<T, U> {
On {
predicate,
projector,
}
}
pub fn extensions<T>(predicate: T) -> On<T, Extensions> {
on(predicate, Extensions)
}
pub fn extension<T, U>(predicate: T) -> On<T, Extension<U>> {
on(predicate, Extension { _ty: PhantomData })
}
pub fn headers<T>(predicate: T) -> On<T, Headers> {
on(predicate, Headers)
}
pub fn method<T>(predicate: T) -> On<T, Method> {
on(predicate, Method)
}
pub fn path<T>(predicate: T) -> On<T, Path> {
on(predicate, Path)
}
pub fn query<T>(predicate: T) -> On<T, Query> {
on(predicate, Query)
}
pub fn uri<T>(predicate: T) -> On<T, Uri> {
on(predicate, Uri)
}
pub(super) fn header<T>(predicate: T, name: HeaderName) -> On<T, Header> {
on(predicate, Header { name })
}
impl<T, U> On<T, U> {
pub fn opt(self) -> Opt<T, U> {
Opt {
predicate: self.predicate,
projector: self.projector,
}
}
}
impl<T, U, Input> Predicate<Input> for On<T, U>
where
for<'a> T: Predicate<U::Output> + 'a,
for<'a> U: Project<Input> + 'a,
{
type Error<'a> = OnError<T::Error<'a>, U::Error<'a>>;
fn cmp<'a>(&'a self, input: &Input) -> Result<(), Self::Error<'a>> {
self.projector
.project(input)
.map_err(OnError::Project)
.and_then(|input| self.predicate.cmp(input).map_err(OnError::Predicate))
}
}
impl<T, U, Input> Predicate<Input> for Opt<T, U>
where
for<'a> T: Predicate<U::Output> + 'a,
for<'a> U: Project<Input> + 'a,
{
type Error<'a> = T::Error<'a>;
fn cmp<'a>(&'a self, input: &Input) -> Result<(), Self::Error<'a>> {
self.projector
.project(input)
.map_or(Ok(()), |input| self.predicate.cmp(input))
}
}