handy_async/
future.rs

1//! Future related functionalities.
2use futures::{Future, IntoFuture, Poll};
3
4/// An extention of the `Future` trait.
5pub trait FutureExt: Future + Sized {
6    /// Polls both AAA and BBB, will select one which is available first.
7    ///
8    /// # Examples
9    ///
10    /// ```
11    /// # extern crate futures;
12    /// # extern crate handy_async;
13    /// use futures::{Future, empty, failed};
14    /// use futures::future::Either;
15    /// use handy_async::future::FutureExt;
16    ///
17    /// # fn main() {
18    /// let future = empty::<(), ()>().select_either(Ok(10) as Result<_, ()>);
19    /// if let Ok(Either::B((_, 10))) = future.wait() {
20    /// } else {
21    ///     panic!();
22    /// }
23    ///
24    /// let future = failed::<(), usize>(10).select_either(empty::<(), ()>());
25    /// if let Err(Either::A((10, _))) = future.wait() {
26    /// } else {
27    ///     panic!();
28    /// }
29    /// # }
30    /// ```
31    fn select_either<B>(self, other: B) -> futures::SelectEither<Self, B::Future>
32    where
33        B: IntoFuture,
34    {
35        impls::select_either(self, other.into_future())
36    }
37}
38impl<T: Future> FutureExt for T {}
39
40pub mod futures {
41    //! `Future` trait implementations.
42    pub use super::impls::SelectEither;
43}
44
45mod impls {
46    use futures::{Future, Poll, Async};
47    use futures::future::Either;
48
49    pub fn select_either<A: Future, B: Future>(a: A, b: B) -> SelectEither<A, B> {
50        SelectEither(Some((a, b)))
51    }
52
53    /// This future polls both AAA and BBB, will select one which is available first.
54    ///
55    /// This is created by calling `FutureExt::select_either` method.
56    pub struct SelectEither<A, B>(Option<(A, B)>);
57    impl<A, B> Future for SelectEither<A, B>
58    where
59        A: Future,
60        B: Future,
61    {
62        type Item = Either<(A::Item, B), (A, B::Item)>;
63        type Error = Either<(A::Error, B), (A, B::Error)>;
64        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
65            let (mut a, mut b) = self.0.take().expect("Cannot poll SelectEither twice");
66            match a.poll() {
67                Err(e) => return Err(Either::A((e, b))),
68                Ok(Async::Ready(v)) => return Ok(Async::Ready(Either::A((v, b)))),
69                Ok(Async::NotReady) => {}
70            }
71            match b.poll() {
72                Err(e) => return Err(Either::B((a, e))),
73                Ok(Async::Ready(v)) => return Ok(Async::Ready(Either::B((a, v)))),
74                Ok(Async::NotReady) => {}
75            }
76            self.0 = Some((a, b));
77            Ok(Async::NotReady)
78        }
79    }
80}
81
82/// `Future` which can be used to represent phases.
83#[derive(Debug)]
84#[allow(missing_docs)]
85pub enum Phase<A, B = A, C = B, D = C, E = D> {
86    A(A),
87    B(B),
88    C(C),
89    D(D),
90    E(E),
91}
92#[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
93impl<A, B, C, D, E> Future for Phase<A, B, C, D, E>
94where
95    A: Future,
96    B: Future,
97    C: Future,
98    D: Future,
99    E: Future,
100{
101    type Item = Phase<A::Item, B::Item, C::Item, D::Item, E::Item>;
102    type Error = Phase<A::Error, B::Error, C::Error, D::Error, E::Error>;
103    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
104        match *self {
105            Phase::A(ref mut f) => f.poll().map(|v| v.map(Phase::A)).map_err(Phase::A),
106            Phase::B(ref mut f) => f.poll().map(|v| v.map(Phase::B)).map_err(Phase::B),
107            Phase::C(ref mut f) => f.poll().map(|v| v.map(Phase::C)).map_err(Phase::C),
108            Phase::D(ref mut f) => f.poll().map(|v| v.map(Phase::D)).map_err(Phase::D),
109            Phase::E(ref mut f) => f.poll().map(|v| v.map(Phase::E)).map_err(Phase::E),
110        }
111    }
112}