1 #![allow(non_snake_case)]
2 
3 use core::fmt;
4 use core::mem;
5 
6 use {Future, Poll, IntoFuture, Async};
7 
8 macro_rules! generate {
9     ($(
10         $(#[$doc:meta])*
11         ($Join:ident, $new:ident, <A, $($B:ident),*>),
12     )*) => ($(
13         $(#[$doc])*
14         #[must_use = "futures do nothing unless polled"]
15         pub struct $Join<A, $($B),*>
16             where A: Future,
17                   $($B: Future<Error=A::Error>),*
18         {
19             a: MaybeDone<A>,
20             $($B: MaybeDone<$B>,)*
21         }
22 
23         impl<A, $($B),*> fmt::Debug for $Join<A, $($B),*>
24             where A: Future + fmt::Debug,
25                   A::Item: fmt::Debug,
26                   $(
27                       $B: Future<Error=A::Error> + fmt::Debug,
28                       $B::Item: fmt::Debug
29                   ),*
30         {
31             fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
32                 fmt.debug_struct(stringify!($Join))
33                     .field("a", &self.a)
34                     $(.field(stringify!($B), &self.$B))*
35                     .finish()
36             }
37         }
38 
39         pub fn $new<A, $($B),*>(a: A, $($B: $B),*) -> $Join<A, $($B),*>
40             where A: Future,
41                   $($B: Future<Error=A::Error>),*
42         {
43             $Join {
44                 a: MaybeDone::NotYet(a),
45                 $($B: MaybeDone::NotYet($B)),*
46             }
47         }
48 
49         impl<A, $($B),*> $Join<A, $($B),*>
50             where A: Future,
51                   $($B: Future<Error=A::Error>),*
52         {
53             fn erase(&mut self) {
54                 self.a = MaybeDone::Gone;
55                 $(self.$B = MaybeDone::Gone;)*
56             }
57         }
58 
59         impl<A, $($B),*> Future for $Join<A, $($B),*>
60             where A: Future,
61                   $($B: Future<Error=A::Error>),*
62         {
63             type Item = (A::Item, $($B::Item),*);
64             type Error = A::Error;
65 
66             fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
67                 let mut all_done = match self.a.poll() {
68                     Ok(done) => done,
69                     Err(e) => {
70                         self.erase();
71                         return Err(e)
72                     }
73                 };
74                 $(
75                     all_done = match self.$B.poll() {
76                         Ok(done) => all_done && done,
77                         Err(e) => {
78                             self.erase();
79                             return Err(e)
80                         }
81                     };
82                 )*
83 
84                 if all_done {
85                     Ok(Async::Ready((self.a.take(), $(self.$B.take()),*)))
86                 } else {
87                     Ok(Async::NotReady)
88                 }
89             }
90         }
91 
92         impl<A, $($B),*> IntoFuture for (A, $($B),*)
93             where A: IntoFuture,
94         $(
95             $B: IntoFuture<Error=A::Error>
96         ),*
97         {
98             type Future = $Join<A::Future, $($B::Future),*>;
99             type Item = (A::Item, $($B::Item),*);
100             type Error = A::Error;
101 
102             fn into_future(self) -> Self::Future {
103                 match self {
104                     (a, $($B),+) => {
105                         $new(
106                             IntoFuture::into_future(a),
107                             $(IntoFuture::into_future($B)),+
108                         )
109                     }
110                 }
111             }
112         }
113 
114     )*)
115 }
116 
117 generate! {
118     /// Future for the `join` combinator, waiting for two futures to
119     /// complete.
120     ///
121     /// This is created by the `Future::join` method.
122     (Join, new, <A, B>),
123 
124     /// Future for the `join3` combinator, waiting for three futures to
125     /// complete.
126     ///
127     /// This is created by the `Future::join3` method.
128     (Join3, new3, <A, B, C>),
129 
130     /// Future for the `join4` combinator, waiting for four futures to
131     /// complete.
132     ///
133     /// This is created by the `Future::join4` method.
134     (Join4, new4, <A, B, C, D>),
135 
136     /// Future for the `join5` combinator, waiting for five futures to
137     /// complete.
138     ///
139     /// This is created by the `Future::join5` method.
140     (Join5, new5, <A, B, C, D, E>),
141 }
142 
143 #[derive(Debug)]
144 enum MaybeDone<A: Future> {
145     NotYet(A),
146     Done(A::Item),
147     Gone,
148 }
149 
150 impl<A: Future> MaybeDone<A> {
poll(&mut self) -> Result<bool, A::Error>151     fn poll(&mut self) -> Result<bool, A::Error> {
152         let res = match *self {
153             MaybeDone::NotYet(ref mut a) => a.poll()?,
154             MaybeDone::Done(_) => return Ok(true),
155             MaybeDone::Gone => panic!("cannot poll Join twice"),
156         };
157         match res {
158             Async::Ready(res) => {
159                 *self = MaybeDone::Done(res);
160                 Ok(true)
161             }
162             Async::NotReady => Ok(false),
163         }
164     }
165 
take(&mut self) -> A::Item166     fn take(&mut self) -> A::Item {
167         match mem::replace(self, MaybeDone::Gone) {
168             MaybeDone::Done(a) => a,
169             _ => panic!(),
170         }
171     }
172 }
173