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
75impl<'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}