#![allow(non_snake_case)] use crate::future::{assert_future, try_maybe_done, TryMaybeDone}; use core::fmt; use core::pin::Pin; use futures_core::future::{Future, TryFuture}; use futures_core::task::{Context, Poll}; use pin_project_lite::pin_project; macro_rules! generate { ($( $(#[$doc:meta])* ($Join:ident, ), )*) => ($( pin_project! { $(#[$doc])* #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct $Join { #[pin] Fut1: TryMaybeDone, $(#[pin] $Fut: TryMaybeDone<$Fut>,)* } } impl fmt::Debug for $Join where Fut1: TryFuture + fmt::Debug, Fut1::Ok: fmt::Debug, Fut1::Error: fmt::Debug, $( $Fut: TryFuture + fmt::Debug, $Fut::Ok: fmt::Debug, $Fut::Error: fmt::Debug, )* { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct(stringify!($Join)) .field("Fut1", &self.Fut1) $(.field(stringify!($Fut), &self.$Fut))* .finish() } } impl $Join where Fut1: TryFuture, $( $Fut: TryFuture ),* { fn new(Fut1: Fut1, $($Fut: $Fut),*) -> Self { Self { Fut1: try_maybe_done(Fut1), $($Fut: try_maybe_done($Fut)),* } } } impl Future for $Join where Fut1: TryFuture, $( $Fut: TryFuture ),* { type Output = Result<(Fut1::Ok, $($Fut::Ok),*), Fut1::Error>; fn poll( self: Pin<&mut Self>, cx: &mut Context<'_> ) -> Poll { let mut all_done = true; let mut futures = self.project(); all_done &= futures.Fut1.as_mut().poll(cx)?.is_ready(); $( all_done &= futures.$Fut.as_mut().poll(cx)?.is_ready(); )* if all_done { Poll::Ready(Ok(( futures.Fut1.take_output().unwrap(), $( futures.$Fut.take_output().unwrap() ),* ))) } else { Poll::Pending } } } )*) } generate! { /// Future for the [`try_join`](try_join()) function. (TryJoin, ), /// Future for the [`try_join3`] function. (TryJoin3, ), /// Future for the [`try_join4`] function. (TryJoin4, ), /// Future for the [`try_join5`] function. (TryJoin5, ), } /// Joins the result of two futures, waiting for them both to complete or /// for one to produce an error. /// /// This function will return a new future which awaits both futures to /// complete. If successful, the returned future will finish with a tuple of /// both results. If unsuccessful, it will complete with the first error /// encountered. /// /// Note that this function consumes the passed futures and returns a /// wrapped version of it. /// /// # Examples /// /// When used on multiple futures that return [`Ok`], `try_join` will return /// [`Ok`] of a tuple of the values: /// /// ``` /// # futures::executor::block_on(async { /// use futures::future; /// /// let a = future::ready(Ok::(1)); /// let b = future::ready(Ok::(2)); /// let pair = future::try_join(a, b); /// /// assert_eq!(pair.await, Ok((1, 2))); /// # }); /// ``` /// /// If one of the futures resolves to an error, `try_join` will return /// that error: /// /// ``` /// # futures::executor::block_on(async { /// use futures::future; /// /// let a = future::ready(Ok::(1)); /// let b = future::ready(Err::(2)); /// let pair = future::try_join(a, b); /// /// assert_eq!(pair.await, Err(2)); /// # }); /// ``` pub fn try_join(future1: Fut1, future2: Fut2) -> TryJoin where Fut1: TryFuture, Fut2: TryFuture, { assert_future::, _>(TryJoin::new(future1, future2)) } /// Same as [`try_join`](try_join()), but with more futures. /// /// # Examples /// /// ``` /// # futures::executor::block_on(async { /// use futures::future; /// /// let a = future::ready(Ok::(1)); /// let b = future::ready(Ok::(2)); /// let c = future::ready(Ok::(3)); /// let tuple = future::try_join3(a, b, c); /// /// assert_eq!(tuple.await, Ok((1, 2, 3))); /// # }); /// ``` pub fn try_join3( future1: Fut1, future2: Fut2, future3: Fut3, ) -> TryJoin3 where Fut1: TryFuture, Fut2: TryFuture, Fut3: TryFuture, { assert_future::, _>(TryJoin3::new( future1, future2, future3, )) } /// Same as [`try_join`](try_join()), but with more futures. /// /// # Examples /// /// ``` /// # futures::executor::block_on(async { /// use futures::future; /// /// let a = future::ready(Ok::(1)); /// let b = future::ready(Ok::(2)); /// let c = future::ready(Ok::(3)); /// let d = future::ready(Ok::(4)); /// let tuple = future::try_join4(a, b, c, d); /// /// assert_eq!(tuple.await, Ok((1, 2, 3, 4))); /// # }); /// ``` pub fn try_join4( future1: Fut1, future2: Fut2, future3: Fut3, future4: Fut4, ) -> TryJoin4 where Fut1: TryFuture, Fut2: TryFuture, Fut3: TryFuture, Fut4: TryFuture, { assert_future::, _>( TryJoin4::new(future1, future2, future3, future4), ) } /// Same as [`try_join`](try_join()), but with more futures. /// /// # Examples /// /// ``` /// # futures::executor::block_on(async { /// use futures::future; /// /// let a = future::ready(Ok::(1)); /// let b = future::ready(Ok::(2)); /// let c = future::ready(Ok::(3)); /// let d = future::ready(Ok::(4)); /// let e = future::ready(Ok::(5)); /// let tuple = future::try_join5(a, b, c, d, e); /// /// assert_eq!(tuple.await, Ok((1, 2, 3, 4, 5))); /// # }); /// ``` pub fn try_join5( future1: Fut1, future2: Fut2, future3: Fut3, future4: Fut4, future5: Fut5, ) -> TryJoin5 where Fut1: TryFuture, Fut2: TryFuture, Fut3: TryFuture, Fut4: TryFuture, Fut5: TryFuture, { assert_future::, _>( TryJoin5::new(future1, future2, future3, future4, future5), ) }