future_utils/
while_driving.rs

1use futures::{Async, Future};
2use std::mem;
3
4pub struct WhileDriving<A, B: Future> {
5    inner: WhileDrivingInner<A, B>,
6}
7
8enum WhileDrivingInner<A, B: Future> {
9    Driving(A, B),
10    Drove(A, Result<B::Item, B::Error>),
11    Finished,
12}
13
14impl<A, B: Future> WhileDriving<A, B> {
15    pub fn new(a: A, b: B) -> WhileDriving<A, B> {
16        WhileDriving {
17            inner: WhileDrivingInner::Driving(a, b),
18        }
19    }
20}
21
22impl<A, B> Future for WhileDriving<A, B>
23where
24    A: Future,
25    B: Future,
26{
27    type Item = (A::Item, Finish<B>);
28    type Error = (A::Error, Finish<B>);
29
30    fn poll(&mut self) -> Result<Async<(A::Item, Finish<B>)>, (A::Error, Finish<B>)> {
31        let inner = mem::replace(&mut self.inner, WhileDrivingInner::Finished);
32        match inner {
33            WhileDrivingInner::Driving(mut a, mut b) => {
34                match a.poll() {
35                    Ok(Async::Ready(x)) => {
36                        let finish = Finish {
37                            state: FinishState::Inner(FinishInner::Running(b)),
38                        };
39                        Ok(Async::Ready((x, finish)))
40                    },
41                    Ok(Async::NotReady) => {
42                        match b.poll() {
43                            Ok(Async::Ready(x)) => {
44                                self.inner = WhileDrivingInner::Drove(a, Ok(x));
45                            },
46                            Ok(Async::NotReady) => {
47                                self.inner = WhileDrivingInner::Driving(a, b);
48                            },
49                            Err(e) => {
50                                self.inner = WhileDrivingInner::Drove(a, Err(e));
51                            },
52                        }
53                        Ok(Async::NotReady)
54                    },
55                    Err(e) => {
56                        let finish = Finish {
57                            state: FinishState::Inner(FinishInner::Running(b)),
58                        };
59                        Err((e, finish))
60                    },
61                }
62            },
63            WhileDrivingInner::Drove(mut a, res) => {
64                match a.poll() {
65                    Ok(Async::Ready(x)) => {
66                        let finish = Finish {
67                            state: FinishState::Inner(FinishInner::Ran(res)),
68                        };
69                        Ok(Async::Ready((x, finish)))
70                    },
71                    Ok(Async::NotReady) => {
72                        self.inner = WhileDrivingInner::Drove(a, res);
73                        Ok(Async::NotReady)
74                    },
75                    Err(e) => {
76                        let finish = Finish {
77                            state: FinishState::Inner(FinishInner::Ran(res)),
78                        };
79                        Err((e, finish))
80                    },
81                }
82            },
83            WhileDrivingInner::Finished => {
84                panic!("poll() called on WhileDriving which has already finished");
85            },
86        }
87    }
88}
89
90/// Future yielded by `WhileDriving` which wraps the future it was driving. Can be resolved to
91/// whatever the original future would resolved to or unpacked using `into_inner`.
92pub struct Finish<B: Future> {
93    state: FinishState<B>,
94}
95
96impl<B: Future> Finish<B> {
97    pub fn into_inner(self) -> FinishInner<B> {
98        match self.state {
99            FinishState::Inner(inner) => inner,
100            FinishState::Finished => {
101                panic!("into_inner() called on Finish which has already finished");
102            },
103        }
104    }
105}
106
107pub enum FinishInner<B: Future> {
108    Running(B),
109    Ran(Result<B::Item, B::Error>),
110}
111
112enum FinishState<B: Future> {
113    Inner(FinishInner<B>),
114    Finished,
115}
116
117impl<B: Future> Future for Finish<B> {
118    type Item = B::Item;
119    type Error = B::Error;
120
121    fn poll(&mut self) -> Result<Async<B::Item>, B::Error> {
122        let state = mem::replace(&mut self.state, FinishState::Finished);
123        match state {
124            FinishState::Inner(FinishInner::Running(mut b)) => {
125                match b.poll() {
126                    Ok(Async::Ready(x)) => {
127                        Ok(Async::Ready(x))
128                    },
129                    Ok(Async::NotReady) => {
130                        self.state = FinishState::Inner(FinishInner::Running(b));
131                        Ok(Async::NotReady)
132                    },
133                    Err(e) => {
134                        Err(e)
135                    },
136                }
137            },
138            FinishState::Inner(FinishInner::Ran(res)) => Ok(Async::Ready(res?)),
139            FinishState::Finished => {
140                panic!("poll() called on Finish which has already finished");
141            },
142        }
143    }
144}
145