finchers/endpoint/
and.rs

1#![cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
2
3use std::fmt;
4
5use futures::future;
6use futures::{Future, Poll};
7
8use common::{Combine, Tuple};
9use endpoint::{ApplyContext, ApplyResult, Endpoint, IntoEndpoint};
10use error::Error;
11
12#[allow(missing_docs)]
13#[derive(Copy, Clone, Debug)]
14pub struct And<E1, E2> {
15    pub(super) e1: E1,
16    pub(super) e2: E2,
17}
18
19impl<'a, E1, E2> Endpoint<'a> for And<E1, E2>
20where
21    E1: Endpoint<'a>,
22    E2: Endpoint<'a>,
23    E1::Output: Combine<E2::Output>,
24{
25    type Output = <E1::Output as Combine<E2::Output>>::Out;
26    type Future = AndFuture<E1::Future, E2::Future>;
27
28    fn apply(&'a self, ecx: &mut ApplyContext<'_>) -> ApplyResult<Self::Future> {
29        let f1 = self.e1.apply(ecx)?;
30        let f2 = self.e2.apply(ecx)?;
31        Ok(AndFuture { inner: f1.join(f2) })
32    }
33}
34
35pub struct AndFuture<F1, F2>
36where
37    F1: Future<Error = Error>,
38    F2: Future<Error = Error>,
39{
40    inner: future::Join<F1, F2>,
41}
42
43impl<F1, F2> fmt::Debug for AndFuture<F1, F2>
44where
45    F1: Future<Error = Error> + fmt::Debug,
46    F2: Future<Error = Error> + fmt::Debug,
47    F1::Item: fmt::Debug,
48    F2::Item: fmt::Debug,
49{
50    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
51        formatter
52            .debug_struct("AndFuture")
53            .field("inner", &self.inner)
54            .finish()
55    }
56}
57
58impl<F1, F2> Future for AndFuture<F1, F2>
59where
60    F1: Future<Error = Error>,
61    F2: Future<Error = Error>,
62    F1::Item: Tuple + Combine<F2::Item>,
63    F2::Item: Tuple,
64{
65    type Item = <F1::Item as Combine<F2::Item>>::Out;
66    type Error = Error;
67
68    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
69        self.inner
70            .poll()
71            .map(|x| x.map(|(v1, v2)| Combine::combine(v1, v2)))
72    }
73}
74
75// ==== tuples ====
76
77impl<'a, E1, E2> IntoEndpoint<'a> for (E1, E2)
78where
79    E1: IntoEndpoint<'a>,
80    E2: IntoEndpoint<'a>,
81    E1::Output: Combine<E2::Output>,
82{
83    type Output = <E1::Output as Combine<E2::Output>>::Out;
84    type Endpoint = And<E1::Endpoint, E2::Endpoint>;
85
86    fn into_endpoint(self) -> Self::Endpoint {
87        (And {
88            e1: self.0.into_endpoint(),
89            e2: self.1.into_endpoint(),
90        }).with_output::<<E1::Output as Combine<E2::Output>>::Out>()
91    }
92}
93
94impl<'a, E1, E2, E3> IntoEndpoint<'a> for (E1, E2, E3)
95where
96    E1: IntoEndpoint<'a>,
97    E2: IntoEndpoint<'a>,
98    E3: IntoEndpoint<'a>,
99    E2::Output: Combine<E3::Output>,
100    E1::Output: Combine<<E2::Output as Combine<E3::Output>>::Out>,
101{
102    type Output = <E1::Output as Combine<<E2::Output as Combine<E3::Output>>::Out>>::Out;
103    type Endpoint = And<E1::Endpoint, And<E2::Endpoint, E3::Endpoint>>;
104
105    fn into_endpoint(self) -> Self::Endpoint {
106        (And {
107            e1: self.0.into_endpoint(),
108            e2: And {
109                e1: self.1.into_endpoint(),
110                e2: self.2.into_endpoint(),
111            },
112        }).with_output::<<E1::Output as Combine<<E2::Output as Combine<E3::Output>>::Out>>::Out>()
113    }
114}
115
116impl<'a, E1, E2, E3, E4> IntoEndpoint<'a> for (E1, E2, E3, E4)
117where
118    E1: IntoEndpoint<'a>,
119    E2: IntoEndpoint<'a>,
120    E3: IntoEndpoint<'a>,
121    E4: IntoEndpoint<'a>,
122    E3::Output: Combine<E4::Output>,
123    E2::Output: Combine<<E3::Output as Combine<E4::Output>>::Out>,
124    E1::Output: Combine<<E2::Output as Combine<<E3::Output as Combine<E4::Output>>::Out>>::Out>,
125{
126    type Output = <E1::Output as Combine<
127        <E2::Output as Combine<<E3::Output as Combine<E4::Output>>::Out>>::Out,
128    >>::Out;
129    type Endpoint = And<E1::Endpoint, And<E2::Endpoint, And<E3::Endpoint, E4::Endpoint>>>;
130
131    fn into_endpoint(self) -> Self::Endpoint {
132        (And {
133            e1: self.0.into_endpoint(),
134            e2: And {
135                e1: self.1.into_endpoint(),
136                e2: And {
137                    e1: self.2.into_endpoint(),
138                    e2: self.3.into_endpoint(),
139                },
140            },
141        }).with_output::<<E1::Output as Combine<
142            <E2::Output as Combine<<E3::Output as Combine<E4::Output>>::Out>>::Out,
143        >>::Out>()
144    }
145}
146
147impl<'a, E1, E2, E3, E4, E5> IntoEndpoint<'a> for (E1, E2, E3, E4, E5)
148where
149    E1: IntoEndpoint<'a>,
150    E2: IntoEndpoint<'a>,
151    E3: IntoEndpoint<'a>,
152    E4: IntoEndpoint<'a>,
153    E5: IntoEndpoint<'a>,
154    E4::Output: Combine<E5::Output>,
155    E3::Output: Combine<<E4::Output as Combine<E5::Output>>::Out>,
156    E2::Output: Combine<<E3::Output as Combine<<E4::Output as Combine<E5::Output>>::Out>>::Out>,
157    E1::Output: Combine<
158        <E2::Output as Combine<
159            <E3::Output as Combine<<E4::Output as Combine<E5::Output>>::Out>>::Out,
160        >>::Out,
161    >,
162{
163    type Output = <E1::Output as Combine<
164        <E2::Output as Combine<
165            <E3::Output as Combine<<E4::Output as Combine<E5::Output>>::Out>>::Out,
166        >>::Out,
167    >>::Out;
168    type Endpoint =
169        And<E1::Endpoint, And<E2::Endpoint, And<E3::Endpoint, And<E4::Endpoint, E5::Endpoint>>>>;
170
171    fn into_endpoint(self) -> Self::Endpoint {
172        (And {
173            e1: self.0.into_endpoint(),
174            e2: And {
175                e1: self.1.into_endpoint(),
176                e2: And {
177                    e1: self.2.into_endpoint(),
178                    e2: And {
179                        e1: self.3.into_endpoint(),
180                        e2: self.4.into_endpoint(),
181                    },
182                },
183            },
184        }).with_output::<<E1::Output as Combine<
185            <E2::Output as Combine<
186                <E3::Output as Combine<<E4::Output as Combine<E5::Output>>::Out>>::Out,
187            >>::Out,
188        >>::Out>()
189    }
190}