#![allow(non_snake_case)] use core::fmt; use core::mem; use {Future, Poll, IntoFuture, Async}; macro_rules! generate { ($( $(#[$doc:meta])* ($Join:ident, $new:ident, ), )*) => ($( $(#[$doc])* #[must_use = "futures do nothing unless polled"] pub struct $Join where A: Future, $($B: Future),* { a: MaybeDone, $($B: MaybeDone<$B>,)* } impl fmt::Debug for $Join where A: Future + fmt::Debug, A::Item: fmt::Debug, $( $B: Future + fmt::Debug, $B::Item: fmt::Debug ),* { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct(stringify!($Join)) .field("a", &self.a) $(.field(stringify!($B), &self.$B))* .finish() } } pub fn $new(a: A, $($B: $B),*) -> $Join where A: Future, $($B: Future),* { $Join { a: MaybeDone::NotYet(a), $($B: MaybeDone::NotYet($B)),* } } impl $Join where A: Future, $($B: Future),* { fn erase(&mut self) { self.a = MaybeDone::Gone; $(self.$B = MaybeDone::Gone;)* } } impl Future for $Join where A: Future, $($B: Future),* { type Item = (A::Item, $($B::Item),*); type Error = A::Error; fn poll(&mut self) -> Poll { let mut all_done = match self.a.poll() { Ok(done) => done, Err(e) => { self.erase(); return Err(e) } }; $( all_done = match self.$B.poll() { Ok(done) => all_done && done, Err(e) => { self.erase(); return Err(e) } }; )* if all_done { Ok(Async::Ready((self.a.take(), $(self.$B.take()),*))) } else { Ok(Async::NotReady) } } } impl IntoFuture for (A, $($B),*) where A: IntoFuture, $( $B: IntoFuture ),* { type Future = $Join; type Item = (A::Item, $($B::Item),*); type Error = A::Error; fn into_future(self) -> Self::Future { match self { (a, $($B),+) => { $new( IntoFuture::into_future(a), $(IntoFuture::into_future($B)),+ ) } } } } )*) } generate! { /// Future for the `join` combinator, waiting for two futures to /// complete. /// /// This is created by the `Future::join` method. (Join, new, ), /// Future for the `join3` combinator, waiting for three futures to /// complete. /// /// This is created by the `Future::join3` method. (Join3, new3, ), /// Future for the `join4` combinator, waiting for four futures to /// complete. /// /// This is created by the `Future::join4` method. (Join4, new4, ), /// Future for the `join5` combinator, waiting for five futures to /// complete. /// /// This is created by the `Future::join5` method. (Join5, new5, ), } #[derive(Debug)] enum MaybeDone { NotYet(A), Done(A::Item), Gone, } impl MaybeDone { fn poll(&mut self) -> Result { let res = match *self { MaybeDone::NotYet(ref mut a) => a.poll()?, MaybeDone::Done(_) => return Ok(true), MaybeDone::Gone => panic!("cannot poll Join twice"), }; match res { Async::Ready(res) => { *self = MaybeDone::Done(res); Ok(true) } Async::NotReady => Ok(false), } } fn take(&mut self) -> A::Item { match mem::replace(self, MaybeDone::Gone) { MaybeDone::Done(a) => a, _ => panic!(), } } }