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