use crate::future::maybe_done::{maybe_done, MaybeDone}; use pin_project_lite::pin_project; use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; pub(crate) fn try_join3( future1: F1, future2: F2, future3: F3, ) -> TryJoin3 where F1: Future>, F2: Future>, F3: Future>, { TryJoin3 { future1: maybe_done(future1), future2: maybe_done(future2), future3: maybe_done(future3), } } pin_project! { pub(crate) struct TryJoin3 where F1: Future, F2: Future, F3: Future, { #[pin] future1: MaybeDone, #[pin] future2: MaybeDone, #[pin] future3: MaybeDone, } } impl Future for TryJoin3 where F1: Future>, F2: Future>, F3: Future>, { type Output = Result<(T1, T2, T3), E>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut all_done = true; let mut me = self.project(); if me.future1.as_mut().poll(cx).is_pending() { all_done = false; } else if me.future1.as_mut().output_mut().unwrap().is_err() { return Poll::Ready(Err(me.future1.take_output().unwrap().err().unwrap())); } if me.future2.as_mut().poll(cx).is_pending() { all_done = false; } else if me.future2.as_mut().output_mut().unwrap().is_err() { return Poll::Ready(Err(me.future2.take_output().unwrap().err().unwrap())); } if me.future3.as_mut().poll(cx).is_pending() { all_done = false; } else if me.future3.as_mut().output_mut().unwrap().is_err() { return Poll::Ready(Err(me.future3.take_output().unwrap().err().unwrap())); } if all_done { Poll::Ready(Ok(( me.future1.take_output().unwrap().ok().unwrap(), me.future2.take_output().unwrap().ok().unwrap(), me.future3.take_output().unwrap().ok().unwrap(), ))) } else { Poll::Pending } } }