1 #![allow(non_snake_case)]
2 
3 use super::assert_future;
4 use crate::future::{maybe_done, MaybeDone};
5 use core::fmt;
6 use core::pin::Pin;
7 use futures_core::future::{FusedFuture, Future};
8 use futures_core::task::{Context, Poll};
9 use pin_project_lite::pin_project;
10 
11 macro_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 
76 generate! {
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 /// ```
join<Fut1, Fut2>(future1: Fut1, future2: Fut2) -> Join<Fut1, Fut2> where Fut1: Future, Fut2: Future,111 pub fn join<Fut1, Fut2>(future1: Fut1, future2: Fut2) -> Join<Fut1, Fut2>
112 where
113     Fut1: Future,
114     Fut2: Future,
115 {
116     let f = Join::new(future1, 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 /// ```
join3<Fut1, Fut2, Fut3>( future1: Fut1, future2: Fut2, future3: Fut3, ) -> Join3<Fut1, Fut2, Fut3> where Fut1: Future, Fut2: Future, Fut3: Future,136 pub fn join3<Fut1, Fut2, Fut3>(
137     future1: Fut1,
138     future2: Fut2,
139     future3: Fut3,
140 ) -> Join3<Fut1, Fut2, Fut3>
141 where
142     Fut1: Future,
143     Fut2: Future,
144     Fut3: Future,
145 {
146     let f = Join3::new(future1, future2, 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 /// ```
join4<Fut1, Fut2, Fut3, Fut4>( future1: Fut1, future2: Fut2, future3: Fut3, future4: Fut4, ) -> Join4<Fut1, Fut2, Fut3, Fut4> where Fut1: Future, Fut2: Future, Fut3: Future, Fut4: Future,167 pub fn join4<Fut1, Fut2, Fut3, Fut4>(
168     future1: Fut1,
169     future2: Fut2,
170     future3: Fut3,
171     future4: Fut4,
172 ) -> Join4<Fut1, Fut2, Fut3, Fut4>
173 where
174     Fut1: Future,
175     Fut2: Future,
176     Fut3: Future,
177     Fut4: Future,
178 {
179     let f = Join4::new(future1, future2, future3, 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 /// ```
join5<Fut1, Fut2, Fut3, Fut4, Fut5>( future1: Fut1, future2: Fut2, future3: Fut3, future4: Fut4, future5: Fut5, ) -> Join5<Fut1, Fut2, Fut3, Fut4, Fut5> where Fut1: Future, Fut2: Future, Fut3: Future, Fut4: Future, Fut5: Future,201 pub 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>
208 where
209     Fut1: Future,
210     Fut2: Future,
211     Fut3: Future,
212     Fut4: Future,
213     Fut5: Future,
214 {
215     let f = Join5::new(future1, future2, future3, future4, future5);
216     assert_future::<
217         (
218             Fut1::Output,
219             Fut2::Output,
220             Fut3::Output,
221             Fut4::Output,
222             Fut5::Output,
223         ),
224         _,
225     >(f)
226 }
227