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
use futures::{Future, Async};
use std::mem;

pub struct FirstOk2<A: Future, B: Future> {
    inner: FirstOk2Inner<A, B>,
}

impl<A: Future, B: Future> FirstOk2<A, B> {
    pub fn new(a: A, b: B) -> FirstOk2<A, B> {
        FirstOk2 {
            inner: FirstOk2Inner::BothRunning(a, b),
        }
    }
}

enum FirstOk2Inner<A: Future, B: Future> {
    BothRunning(A, B),
    RunningA(A, B::Error),
    RunningB(A::Error, B),
    Finished,
}

impl<A, B> Future for FirstOk2<A, B>
where
    A: Future,
    B: Future<Item=A::Item>
{
    type Item = A::Item;
    type Error = (A::Error, B::Error);

    fn poll(&mut self) -> Result<Async<A::Item>, (A::Error, B::Error)> {
        let inner = mem::replace(&mut self.inner, FirstOk2Inner::Finished);
        match inner {
            FirstOk2Inner::BothRunning(mut a, mut b) => {
                match a.poll() {
                    Ok(Async::Ready(x)) => Ok(Async::Ready(x)),
                    Ok(Async::NotReady) => {
                        match b.poll() {
                            Ok(Async::Ready(x)) => Ok(Async::Ready(x)),
                            Ok(Async::NotReady) => {
                                self.inner = FirstOk2Inner::BothRunning(a, b);
                                Ok(Async::NotReady)
                            },
                            Err(eb) => {
                                self.inner = FirstOk2Inner::RunningA(a, eb);
                                Ok(Async::NotReady)
                            },
                        }
                    },
                    Err(ea) => {
                        match b.poll() {
                            Ok(Async::Ready(x)) => Ok(Async::Ready(x)),
                            Ok(Async::NotReady) => {
                                self.inner = FirstOk2Inner::RunningB(ea, b);
                                Ok(Async::NotReady)
                            },
                            Err(eb) => Err((ea, eb)),
                        }
                    },
                }
            },
            FirstOk2Inner::RunningA(mut a, eb) => {
                match a.poll() {
                    Ok(Async::Ready(x)) => Ok(Async::Ready(x)),
                    Ok(Async::NotReady) => {
                        self.inner = FirstOk2Inner::RunningA(a, eb);
                        Ok(Async::NotReady)
                    },
                    Err(ea) => Err((ea, eb)),
                }
            },
            FirstOk2Inner::RunningB(ea, mut b) => {
                match b.poll() {
                    Ok(Async::Ready(x)) => Ok(Async::Ready(x)),
                    Ok(Async::NotReady) => {
                        self.inner = FirstOk2Inner::RunningB(ea, b);
                        Ok(Async::NotReady)
                    },
                    Err(eb) => Err((ea, eb)),
                }
            },
            FirstOk2Inner::Finished => {
                panic!("poll() called on FirstOk2 which has already finished");
            },
        }
    }
}