1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
//! Future related functionalities.
use futures::{Future, IntoFuture, Poll};

/// An extention of the `Future` trait.
pub trait FutureExt: Future + Sized {
    /// Polls both AAA and BBB, will select one which is available first.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate futures;
    /// # extern crate handy_async;
    /// use futures::{Future, empty, failed};
    /// use futures::future::Either;
    /// use handy_async::future::FutureExt;
    ///
    /// # fn main() {
    /// let future = empty::<(), ()>().select_either(Ok(10) as Result<_, ()>);
    /// if let Ok(Either::B((_, 10))) = future.wait() {
    /// } else {
    ///     panic!();
    /// }
    ///
    /// let future = failed::<(), usize>(10).select_either(empty::<(), ()>());
    /// if let Err(Either::A((10, _))) = future.wait() {
    /// } else {
    ///     panic!();
    /// }
    /// # }
    /// ```
    fn select_either<B>(self, other: B) -> futures::SelectEither<Self, B::Future>
    where
        B: IntoFuture,
    {
        impls::select_either(self, other.into_future())
    }
}
impl<T: Future> FutureExt for T {}

pub mod futures {
    //! `Future` trait implementations.
    pub use super::impls::SelectEither;
}

mod impls {
    use futures::{Future, Poll, Async};
    use futures::future::Either;

    pub fn select_either<A: Future, B: Future>(a: A, b: B) -> SelectEither<A, B> {
        SelectEither(Some((a, b)))
    }

    /// This future polls both AAA and BBB, will select one which is available first.
    ///
    /// This is created by calling `FutureExt::select_either` method.
    pub struct SelectEither<A, B>(Option<(A, B)>);
    impl<A, B> Future for SelectEither<A, B>
    where
        A: Future,
        B: Future,
    {
        type Item = Either<(A::Item, B), (A, B::Item)>;
        type Error = Either<(A::Error, B), (A, B::Error)>;
        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            let (mut a, mut b) = self.0.take().expect("Cannot poll SelectEither twice");
            match a.poll() {
                Err(e) => return Err(Either::A((e, b))),
                Ok(Async::Ready(v)) => return Ok(Async::Ready(Either::A((v, b)))),
                Ok(Async::NotReady) => {}
            }
            match b.poll() {
                Err(e) => return Err(Either::B((a, e))),
                Ok(Async::Ready(v)) => return Ok(Async::Ready(Either::B((a, v)))),
                Ok(Async::NotReady) => {}
            }
            self.0 = Some((a, b));
            Ok(Async::NotReady)
        }
    }
}

/// `Future` which can be used to represent phases.
#[derive(Debug)]
#[allow(missing_docs)]
pub enum Phase<A, B = A, C = B, D = C, E = D> {
    A(A),
    B(B),
    C(C),
    D(D),
    E(E),
}
#[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
impl<A, B, C, D, E> Future for Phase<A, B, C, D, E>
where
    A: Future,
    B: Future,
    C: Future,
    D: Future,
    E: Future,
{
    type Item = Phase<A::Item, B::Item, C::Item, D::Item, E::Item>;
    type Error = Phase<A::Error, B::Error, C::Error, D::Error, E::Error>;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match *self {
            Phase::A(ref mut f) => f.poll().map(|v| v.map(Phase::A)).map_err(Phase::A),
            Phase::B(ref mut f) => f.poll().map(|v| v.map(Phase::B)).map_err(Phase::B),
            Phase::C(ref mut f) => f.poll().map(|v| v.map(Phase::C)).map_err(Phase::C),
            Phase::D(ref mut f) => f.poll().map(|v| v.map(Phase::D)).map_err(Phase::D),
            Phase::E(ref mut f) => f.poll().map(|v| v.map(Phase::E)).map_err(Phase::E),
        }
    }
}