1 //! Definition of the `SelectOk` combinator, finding the first successful future
2 //! in a list.
3 
4 use std::mem;
5 use std::prelude::v1::*;
6 
7 use {Future, IntoFuture, Poll, Async};
8 
9 /// Future for the `select_ok` combinator, waiting for one of any of a list of
10 /// futures to successfully complete. Unlike `select_all`, this future ignores all
11 /// but the last error, if there are any.
12 ///
13 /// This is created by the `select_ok` function.
14 #[derive(Debug)]
15 #[must_use = "futures do nothing unless polled"]
16 pub struct SelectOk<A> where A: Future {
17     inner: Vec<A>,
18 }
19 
20 /// Creates a new future which will select the first successful future over a list of futures.
21 ///
22 /// The returned future will wait for any future within `iter` to be ready and Ok. Unlike
23 /// `select_all`, this will only return the first successful completion, or the last
24 /// failure. This is useful in contexts where any success is desired and failures
25 /// are ignored, unless all the futures fail.
26 ///
27 /// # Panics
28 ///
29 /// This function will panic if the iterator specified contains no items.
select_ok<I>(iter: I) -> SelectOk<<I::Item as IntoFuture>::Future> where I: IntoIterator, I::Item: IntoFuture,30 pub fn select_ok<I>(iter: I) -> SelectOk<<I::Item as IntoFuture>::Future>
31     where I: IntoIterator,
32           I::Item: IntoFuture,
33 {
34     let ret = SelectOk {
35         inner: iter.into_iter()
36                    .map(|a| a.into_future())
37                    .collect(),
38     };
39     assert!(ret.inner.len() > 0);
40     ret
41 }
42 
43 impl<A> Future for SelectOk<A> where A: Future {
44     type Item = (A::Item, Vec<A>);
45     type Error = A::Error;
46 
poll(&mut self) -> Poll<Self::Item, Self::Error>47     fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
48         // loop until we've either exhausted all errors, a success was hit, or nothing is ready
49         loop {
50             let item = self.inner.iter_mut().enumerate().filter_map(|(i, f)| {
51                 match f.poll() {
52                     Ok(Async::NotReady) => None,
53                     Ok(Async::Ready(e)) => Some((i, Ok(e))),
54                     Err(e) => Some((i, Err(e))),
55                 }
56             }).next();
57 
58             match item {
59                 Some((idx, res)) => {
60                     // always remove Ok or Err, if it's not the last Err continue looping
61                     drop(self.inner.remove(idx));
62                     match res {
63                         Ok(e) => {
64                             let rest = mem::replace(&mut self.inner, Vec::new());
65                             return Ok(Async::Ready((e, rest)))
66                         },
67                         Err(e) => {
68                             if self.inner.is_empty() {
69                                 return Err(e)
70                             }
71                         },
72                     }
73                 }
74                 None => {
75                     // based on the filter above, nothing is ready, return
76                     return Ok(Async::NotReady)
77                 },
78             }
79         }
80     }
81 }
82