1 #![allow(non_snake_case)]
2 
3 use crate::future::{assert_future, try_maybe_done, TryMaybeDone};
4 use core::fmt;
5 use core::pin::Pin;
6 use futures_core::future::{Future, TryFuture};
7 use futures_core::task::{Context, Poll};
8 use pin_project_lite::pin_project;
9 
10 macro_rules! generate {
11     ($(
12         $(#[$doc:meta])*
13         ($Join:ident, <Fut1, $($Fut:ident),*>),
14     )*) => ($(
15         pin_project! {
16             $(#[$doc])*
17             #[must_use = "futures do nothing unless you `.await` or poll them"]
18             pub struct $Join<Fut1: TryFuture, $($Fut: TryFuture),*> {
19                 #[pin] Fut1: TryMaybeDone<Fut1>,
20                 $(#[pin] $Fut: TryMaybeDone<$Fut>,)*
21             }
22         }
23 
24         impl<Fut1, $($Fut),*> fmt::Debug for $Join<Fut1, $($Fut),*>
25         where
26             Fut1: TryFuture + fmt::Debug,
27             Fut1::Ok: fmt::Debug,
28             Fut1::Error: fmt::Debug,
29             $(
30                 $Fut: TryFuture + fmt::Debug,
31                 $Fut::Ok: fmt::Debug,
32                 $Fut::Error: fmt::Debug,
33             )*
34         {
35             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36                 f.debug_struct(stringify!($Join))
37                     .field("Fut1", &self.Fut1)
38                     $(.field(stringify!($Fut), &self.$Fut))*
39                     .finish()
40             }
41         }
42 
43         impl<Fut1, $($Fut),*> $Join<Fut1, $($Fut),*>
44         where
45             Fut1: TryFuture,
46             $(
47                 $Fut: TryFuture<Error=Fut1::Error>
48             ),*
49         {
50             fn new(Fut1: Fut1, $($Fut: $Fut),*) -> Self {
51                 Self {
52                     Fut1: try_maybe_done(Fut1),
53                     $($Fut: try_maybe_done($Fut)),*
54                 }
55             }
56         }
57 
58         impl<Fut1, $($Fut),*> Future for $Join<Fut1, $($Fut),*>
59         where
60             Fut1: TryFuture,
61             $(
62                 $Fut: TryFuture<Error=Fut1::Error>
63             ),*
64         {
65             type Output = Result<(Fut1::Ok, $($Fut::Ok),*), Fut1::Error>;
66 
67             fn poll(
68                 self: Pin<&mut Self>, cx: &mut Context<'_>
69             ) -> Poll<Self::Output> {
70                 let mut all_done = true;
71                 let mut futures = self.project();
72                 all_done &= futures.Fut1.as_mut().poll(cx)?.is_ready();
73                 $(
74                     all_done &= futures.$Fut.as_mut().poll(cx)?.is_ready();
75                 )*
76 
77                 if all_done {
78                     Poll::Ready(Ok((
79                         futures.Fut1.take_output().unwrap(),
80                         $(
81                             futures.$Fut.take_output().unwrap()
82                         ),*
83                     )))
84                 } else {
85                     Poll::Pending
86                 }
87             }
88         }
89     )*)
90 }
91 
92 generate! {
93     /// Future for the [`try_join`](try_join()) function.
94     (TryJoin, <Fut1, Fut2>),
95 
96     /// Future for the [`try_join3`] function.
97     (TryJoin3, <Fut1, Fut2, Fut3>),
98 
99     /// Future for the [`try_join4`] function.
100     (TryJoin4, <Fut1, Fut2, Fut3, Fut4>),
101 
102     /// Future for the [`try_join5`] function.
103     (TryJoin5, <Fut1, Fut2, Fut3, Fut4, Fut5>),
104 }
105 
106 /// Joins the result of two futures, waiting for them both to complete or
107 /// for one to produce an error.
108 ///
109 /// This function will return a new future which awaits both futures to
110 /// complete. If successful, the returned future will finish with a tuple of
111 /// both results. If unsuccessful, it will complete with the first error
112 /// encountered.
113 ///
114 /// Note that this function consumes the passed futures and returns a
115 /// wrapped version of it.
116 ///
117 /// # Examples
118 ///
119 /// When used on multiple futures that return [`Ok`], `try_join` will return
120 /// [`Ok`] of a tuple of the values:
121 ///
122 /// ```
123 /// # futures::executor::block_on(async {
124 /// use futures::future;
125 ///
126 /// let a = future::ready(Ok::<i32, i32>(1));
127 /// let b = future::ready(Ok::<i32, i32>(2));
128 /// let pair = future::try_join(a, b);
129 ///
130 /// assert_eq!(pair.await, Ok((1, 2)));
131 /// # });
132 /// ```
133 ///
134 /// If one of the futures resolves to an error, `try_join` will return
135 /// that error:
136 ///
137 /// ```
138 /// # futures::executor::block_on(async {
139 /// use futures::future;
140 ///
141 /// let a = future::ready(Ok::<i32, i32>(1));
142 /// let b = future::ready(Err::<i32, i32>(2));
143 /// let pair = future::try_join(a, b);
144 ///
145 /// assert_eq!(pair.await, Err(2));
146 /// # });
147 /// ```
try_join<Fut1, Fut2>(future1: Fut1, future2: Fut2) -> TryJoin<Fut1, Fut2> where Fut1: TryFuture, Fut2: TryFuture<Error = Fut1::Error>,148 pub fn try_join<Fut1, Fut2>(future1: Fut1, future2: Fut2) -> TryJoin<Fut1, Fut2>
149 where
150     Fut1: TryFuture,
151     Fut2: TryFuture<Error = Fut1::Error>,
152 {
153     assert_future::<Result<(Fut1::Ok, Fut2::Ok), Fut1::Error>, _>(TryJoin::new(future1, future2))
154 }
155 
156 /// Same as [`try_join`](try_join()), but with more futures.
157 ///
158 /// # Examples
159 ///
160 /// ```
161 /// # futures::executor::block_on(async {
162 /// use futures::future;
163 ///
164 /// let a = future::ready(Ok::<i32, i32>(1));
165 /// let b = future::ready(Ok::<i32, i32>(2));
166 /// let c = future::ready(Ok::<i32, i32>(3));
167 /// let tuple = future::try_join3(a, b, c);
168 ///
169 /// assert_eq!(tuple.await, Ok((1, 2, 3)));
170 /// # });
171 /// ```
try_join3<Fut1, Fut2, Fut3>( future1: Fut1, future2: Fut2, future3: Fut3, ) -> TryJoin3<Fut1, Fut2, Fut3> where Fut1: TryFuture, Fut2: TryFuture<Error = Fut1::Error>, Fut3: TryFuture<Error = Fut1::Error>,172 pub fn try_join3<Fut1, Fut2, Fut3>(
173     future1: Fut1,
174     future2: Fut2,
175     future3: Fut3,
176 ) -> TryJoin3<Fut1, Fut2, Fut3>
177 where
178     Fut1: TryFuture,
179     Fut2: TryFuture<Error = Fut1::Error>,
180     Fut3: TryFuture<Error = Fut1::Error>,
181 {
182     assert_future::<Result<(Fut1::Ok, Fut2::Ok, Fut3::Ok), Fut1::Error>, _>(TryJoin3::new(
183         future1, future2, future3,
184     ))
185 }
186 
187 /// Same as [`try_join`](try_join()), but with more futures.
188 ///
189 /// # Examples
190 ///
191 /// ```
192 /// # futures::executor::block_on(async {
193 /// use futures::future;
194 ///
195 /// let a = future::ready(Ok::<i32, i32>(1));
196 /// let b = future::ready(Ok::<i32, i32>(2));
197 /// let c = future::ready(Ok::<i32, i32>(3));
198 /// let d = future::ready(Ok::<i32, i32>(4));
199 /// let tuple = future::try_join4(a, b, c, d);
200 ///
201 /// assert_eq!(tuple.await, Ok((1, 2, 3, 4)));
202 /// # });
203 /// ```
try_join4<Fut1, Fut2, Fut3, Fut4>( future1: Fut1, future2: Fut2, future3: Fut3, future4: Fut4, ) -> TryJoin4<Fut1, Fut2, Fut3, Fut4> where Fut1: TryFuture, Fut2: TryFuture<Error = Fut1::Error>, Fut3: TryFuture<Error = Fut1::Error>, Fut4: TryFuture<Error = Fut1::Error>,204 pub fn try_join4<Fut1, Fut2, Fut3, Fut4>(
205     future1: Fut1,
206     future2: Fut2,
207     future3: Fut3,
208     future4: Fut4,
209 ) -> TryJoin4<Fut1, Fut2, Fut3, Fut4>
210 where
211     Fut1: TryFuture,
212     Fut2: TryFuture<Error = Fut1::Error>,
213     Fut3: TryFuture<Error = Fut1::Error>,
214     Fut4: TryFuture<Error = Fut1::Error>,
215 {
216     assert_future::<Result<(Fut1::Ok, Fut2::Ok, Fut3::Ok, Fut4::Ok), Fut1::Error>, _>(
217         TryJoin4::new(future1, future2, future3, future4),
218     )
219 }
220 
221 /// Same as [`try_join`](try_join()), but with more futures.
222 ///
223 /// # Examples
224 ///
225 /// ```
226 /// # futures::executor::block_on(async {
227 /// use futures::future;
228 ///
229 /// let a = future::ready(Ok::<i32, i32>(1));
230 /// let b = future::ready(Ok::<i32, i32>(2));
231 /// let c = future::ready(Ok::<i32, i32>(3));
232 /// let d = future::ready(Ok::<i32, i32>(4));
233 /// let e = future::ready(Ok::<i32, i32>(5));
234 /// let tuple = future::try_join5(a, b, c, d, e);
235 ///
236 /// assert_eq!(tuple.await, Ok((1, 2, 3, 4, 5)));
237 /// # });
238 /// ```
try_join5<Fut1, Fut2, Fut3, Fut4, Fut5>( future1: Fut1, future2: Fut2, future3: Fut3, future4: Fut4, future5: Fut5, ) -> TryJoin5<Fut1, Fut2, Fut3, Fut4, Fut5> where Fut1: TryFuture, Fut2: TryFuture<Error = Fut1::Error>, Fut3: TryFuture<Error = Fut1::Error>, Fut4: TryFuture<Error = Fut1::Error>, Fut5: TryFuture<Error = Fut1::Error>,239 pub fn try_join5<Fut1, Fut2, Fut3, Fut4, Fut5>(
240     future1: Fut1,
241     future2: Fut2,
242     future3: Fut3,
243     future4: Fut4,
244     future5: Fut5,
245 ) -> TryJoin5<Fut1, Fut2, Fut3, Fut4, Fut5>
246 where
247     Fut1: TryFuture,
248     Fut2: TryFuture<Error = Fut1::Error>,
249     Fut3: TryFuture<Error = Fut1::Error>,
250     Fut4: TryFuture<Error = Fut1::Error>,
251     Fut5: TryFuture<Error = Fut1::Error>,
252 {
253     assert_future::<Result<(Fut1::Ok, Fut2::Ok, Fut3::Ok, Fut4::Ok, Fut5::Ok), Fut1::Error>, _>(
254         TryJoin5::new(future1, future2, future3, future4, future5),
255     )
256 }
257