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