futures_util/future/
try_join.rs

1#![allow(non_snake_case)]
2
3use crate::future::{assert_future, try_maybe_done, TryMaybeDone};
4use core::fmt;
5use core::pin::Pin;
6use futures_core::future::{Future, TryFuture};
7use futures_core::task::{Context, Poll};
8use pin_project_lite::pin_project;
9
10macro_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
92generate! {
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/// ```
148pub fn try_join<Fut1, Fut2>(future1: Fut1, future2: Fut2) -> TryJoin<Fut1, Fut2>
149where
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/// ```
172pub fn try_join3<Fut1, Fut2, Fut3>(
173    future1: Fut1,
174    future2: Fut2,
175    future3: Fut3,
176) -> TryJoin3<Fut1, Fut2, Fut3>
177where
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/// ```
204pub 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>
210where
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/// ```
239pub 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>
246where
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}