1extern crate futures;
30
31use futures::{Async, Future, IntoFuture, Poll};
32use std::mem;
33
34enum StateMachine<Original, Resulting, F> {
35 First(F, Original),
36 Second(Resulting),
37 EmptyState,
38}
39
40pub struct AndThen2<Original, Resulting, F>(StateMachine<Original, Resulting, F>);
42
43impl<Original, Intermediate, F> Future for StateMachine<Original, Intermediate::Future, F>
44where
45 Original: Future,
46 Intermediate: IntoFuture,
47 F: FnOnce(Original::Item) -> Intermediate,
48{
49 type Item = Result<Intermediate::Item, Intermediate::Error>;
50 type Error = Original::Error;
51
52 fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
53 loop {
54 let previous_state = mem::replace(self, StateMachine::EmptyState);
55 let new_state = match previous_state {
56 StateMachine::First(f, mut original) => match original.poll()? {
57 Async::Ready(x) => StateMachine::Second(f(x).into_future()),
58 Async::NotReady => {
59 mem::replace(self, StateMachine::First(f, original));
60 return Ok(Async::NotReady);
61 }
62 },
63 StateMachine::Second(mut resulting) => match resulting.poll() {
64 Err(e) => return Ok(Async::Ready(Err(e))),
65 Ok(Async::Ready(res)) => return Ok(Async::Ready(Ok(res))),
66 Ok(Async::NotReady) => {
67 mem::replace(self, StateMachine::Second(resulting));
68 return Ok(Async::NotReady);
69 }
70 },
71 StateMachine::EmptyState => panic!("poll() called after completion"),
72 };
73 mem::replace(self, new_state);
74 }
75 }
76}
77
78impl<Original, Intermediate, F> Future for AndThen2<Original, Intermediate::Future, F>
79where
80 Original: Future,
81 Intermediate: IntoFuture,
82 F: FnOnce(Original::Item) -> Intermediate,
83{
84 type Item = Result<Intermediate::Item, Intermediate::Error>;
85 type Error = Original::Error;
86
87 fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
88 self.0.poll()
89 }
90}
91
92pub trait FutureExt: Future {
94 fn and_then2<F, B>(self, f: F) -> AndThen2<Self, B::Future, F>
102 where
103 B: IntoFuture,
104 F: FnOnce(Self::Item) -> B,
105 Self: Sized,
106 {
107 AndThen2(StateMachine::First(f, self))
108 }
109}
110
111impl<T: Future> FutureExt for T {}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[derive(Debug, PartialEq)]
118 struct Err1;
119 #[derive(Debug, PartialEq)]
120 struct Err2;
121
122 fn plus_one_ok(x: usize) -> impl IntoFuture<Item = usize, Error = Err2> {
123 futures::future::ok(x + 1)
124 }
125
126 fn just_err(_: usize) -> impl IntoFuture<Item = usize, Error = Err2> {
127 futures::future::err(Err2)
128 }
129
130 #[test]
131 fn test_ok_ok() {
132 let f1 = futures::future::ok::<_, Err1>(1);
133 let combined = f1.and_then2(plus_one_ok);
134 assert_eq!(Ok(Ok(2)), combined.wait());
135 }
136
137 #[test]
138 fn test_ok_err() {
139 let f1 = futures::future::ok::<_, Err1>(1);
140 let combined = f1.and_then2(just_err);
141 assert_eq!(Ok(Err(Err2)), combined.wait());
142 }
143
144 #[test]
145 fn test_err_ok() {
146 let f1 = futures::future::err(Err1);
147 let combined = f1.and_then2(plus_one_ok);
148 assert_eq!(Err(Err1), combined.wait());
149 }
150
151 #[test]
152 fn test_err_err() {
153 let f1 = futures::future::err(Err1);
154 let combined = f1.and_then2(just_err);
155 assert_eq!(Err(Err1), combined.wait());
156 }
157}