summaryrefslogtreecommitdiffstats
path: root/smtp/src/resolve_all.rs
blob: 69d3c8b701858af82ff022816cf4584b273aee66 (plain)
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
use std::mem;
use std::iter::FromIterator;

use futures::{Future, Async, Poll};

pub enum AltFuse<F: Future> {
    Future(F),
    Resolved(Result<F::Item, F::Error>)
}

impl<F> Future for AltFuse<F>
    where F: Future
{
    type Item = ();
    //TODO[futures/v>=0.2 |rust/! type]: use Never or !
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let result = match *self {
            AltFuse::Resolved(_) => return Ok(Async::Ready(())),
            AltFuse::Future(ref mut fut) => match fut.poll() {
                Ok(Async::NotReady) => return Ok(Async::NotReady),
                Ok(Async::Ready(val)) => Ok(val),
                Err(err) => Err(err)
            }
        };

        *self = AltFuse::Resolved(result);
        Ok(Async::Ready(()))
    }
}


pub struct ResolveAll<F>
    where F: Future
{
    all: Vec<AltFuse<F>>
}

impl<F> Future for ResolveAll<F>
    where F: Future
{
    type Item = Vec<Result<F::Item, F::Error>>;
    //TODO[futures >= 0.2/rust ! type]: use Never or !
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut any_not_ready = false;
        for fut in self.all.iter_mut() {
            if let Ok(Async::NotReady) = fut.poll() {
                any_not_ready = true;
            }
        }
        if any_not_ready {
            Ok(Async::NotReady)
        } else {
            let results = mem::replace(&mut self.all, Vec::new())
                .into_iter().map(|alt_fuse_fut| match alt_fuse_fut {
                    AltFuse::Resolved(res) => res,
                    AltFuse::Future(_) => unreachable!()
                })
                .collect();
            Ok(Async::Ready(results))
        }
    }
}

impl<I> FromIterator<I> for ResolveAll<I>
    where I: Future
{
    fn from_iter<T>(all: T) -> Self
        where T: IntoIterator<Item = I>
    {
         let all = all
            .into_iter()
            .map(|fut| AltFuse::Future(fut))
            .collect();

        ResolveAll { all }
    }
}