#![cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
use std::fmt;
use futures::future;
use futures::{Future, Poll};
use common::{Combine, Tuple};
use endpoint::{ApplyContext, ApplyResult, Endpoint, IntoEndpoint};
use error::Error;
#[allow(missing_docs)]
#[derive(Copy, Clone, Debug)]
pub struct And<E1, E2> {
pub(super) e1: E1,
pub(super) e2: E2,
}
impl<'a, E1, E2> Endpoint<'a> for And<E1, E2>
where
E1: Endpoint<'a>,
E2: Endpoint<'a>,
E1::Output: Combine<E2::Output>,
{
type Output = <E1::Output as Combine<E2::Output>>::Out;
type Future = AndFuture<E1::Future, E2::Future>;
fn apply(&'a self, ecx: &mut ApplyContext<'_>) -> ApplyResult<Self::Future> {
let f1 = self.e1.apply(ecx)?;
let f2 = self.e2.apply(ecx)?;
Ok(AndFuture { inner: f1.join(f2) })
}
}
pub struct AndFuture<F1, F2>
where
F1: Future<Error = Error>,
F2: Future<Error = Error>,
{
inner: future::Join<F1, F2>,
}
impl<F1, F2> fmt::Debug for AndFuture<F1, F2>
where
F1: Future<Error = Error> + fmt::Debug,
F2: Future<Error = Error> + fmt::Debug,
F1::Item: fmt::Debug,
F2::Item: fmt::Debug,
{
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("AndFuture")
.field("inner", &self.inner)
.finish()
}
}
impl<F1, F2> Future for AndFuture<F1, F2>
where
F1: Future<Error = Error>,
F2: Future<Error = Error>,
F1::Item: Tuple + Combine<F2::Item>,
F2::Item: Tuple,
{
type Item = <F1::Item as Combine<F2::Item>>::Out;
type Error = Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.inner
.poll()
.map(|x| x.map(|(v1, v2)| Combine::combine(v1, v2)))
}
}
impl<'a, E1, E2> IntoEndpoint<'a> for (E1, E2)
where
E1: IntoEndpoint<'a>,
E2: IntoEndpoint<'a>,
E1::Output: Combine<E2::Output>,
{
type Output = <E1::Output as Combine<E2::Output>>::Out;
type Endpoint = And<E1::Endpoint, E2::Endpoint>;
fn into_endpoint(self) -> Self::Endpoint {
(And {
e1: self.0.into_endpoint(),
e2: self.1.into_endpoint(),
}).with_output::<<E1::Output as Combine<E2::Output>>::Out>()
}
}
impl<'a, E1, E2, E3> IntoEndpoint<'a> for (E1, E2, E3)
where
E1: IntoEndpoint<'a>,
E2: IntoEndpoint<'a>,
E3: IntoEndpoint<'a>,
E2::Output: Combine<E3::Output>,
E1::Output: Combine<<E2::Output as Combine<E3::Output>>::Out>,
{
type Output = <E1::Output as Combine<<E2::Output as Combine<E3::Output>>::Out>>::Out;
type Endpoint = And<E1::Endpoint, And<E2::Endpoint, E3::Endpoint>>;
fn into_endpoint(self) -> Self::Endpoint {
(And {
e1: self.0.into_endpoint(),
e2: And {
e1: self.1.into_endpoint(),
e2: self.2.into_endpoint(),
},
}).with_output::<<E1::Output as Combine<<E2::Output as Combine<E3::Output>>::Out>>::Out>()
}
}
impl<'a, E1, E2, E3, E4> IntoEndpoint<'a> for (E1, E2, E3, E4)
where
E1: IntoEndpoint<'a>,
E2: IntoEndpoint<'a>,
E3: IntoEndpoint<'a>,
E4: IntoEndpoint<'a>,
E3::Output: Combine<E4::Output>,
E2::Output: Combine<<E3::Output as Combine<E4::Output>>::Out>,
E1::Output: Combine<<E2::Output as Combine<<E3::Output as Combine<E4::Output>>::Out>>::Out>,
{
type Output = <E1::Output as Combine<
<E2::Output as Combine<<E3::Output as Combine<E4::Output>>::Out>>::Out,
>>::Out;
type Endpoint = And<E1::Endpoint, And<E2::Endpoint, And<E3::Endpoint, E4::Endpoint>>>;
fn into_endpoint(self) -> Self::Endpoint {
(And {
e1: self.0.into_endpoint(),
e2: And {
e1: self.1.into_endpoint(),
e2: And {
e1: self.2.into_endpoint(),
e2: self.3.into_endpoint(),
},
},
}).with_output::<<E1::Output as Combine<
<E2::Output as Combine<<E3::Output as Combine<E4::Output>>::Out>>::Out,
>>::Out>()
}
}
impl<'a, E1, E2, E3, E4, E5> IntoEndpoint<'a> for (E1, E2, E3, E4, E5)
where
E1: IntoEndpoint<'a>,
E2: IntoEndpoint<'a>,
E3: IntoEndpoint<'a>,
E4: IntoEndpoint<'a>,
E5: IntoEndpoint<'a>,
E4::Output: Combine<E5::Output>,
E3::Output: Combine<<E4::Output as Combine<E5::Output>>::Out>,
E2::Output: Combine<<E3::Output as Combine<<E4::Output as Combine<E5::Output>>::Out>>::Out>,
E1::Output: Combine<
<E2::Output as Combine<
<E3::Output as Combine<<E4::Output as Combine<E5::Output>>::Out>>::Out,
>>::Out,
>,
{
type Output = <E1::Output as Combine<
<E2::Output as Combine<
<E3::Output as Combine<<E4::Output as Combine<E5::Output>>::Out>>::Out,
>>::Out,
>>::Out;
type Endpoint =
And<E1::Endpoint, And<E2::Endpoint, And<E3::Endpoint, And<E4::Endpoint, E5::Endpoint>>>>;
fn into_endpoint(self) -> Self::Endpoint {
(And {
e1: self.0.into_endpoint(),
e2: And {
e1: self.1.into_endpoint(),
e2: And {
e1: self.2.into_endpoint(),
e2: And {
e1: self.3.into_endpoint(),
e2: self.4.into_endpoint(),
},
},
},
}).with_output::<<E1::Output as Combine<
<E2::Output as Combine<
<E3::Output as Combine<<E4::Output as Combine<E5::Output>>::Out>>::Out,
>>::Out,
>>::Out>()
}
}