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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use futures::future::Either;
use futures::StreamExt;
use std::future::Future;

pub async fn both<L, R>(future1: L, future2: R) -> bool
where
    L: Future<Output = bool>,
    R: Future<Output = bool>,
{
    futures::pin_mut!(future1);
    futures::pin_mut!(future2);
    match futures::future::select(future1, future2).await {
        Either::Left((res1, future2)) => res1 && future2.await,
        Either::Right((res2, future1)) => res2 && future1.await,
    }
}

#[cfg(test)]
mod both_tests {
    use super::both;
    use async_std::task;
    use futures::future;

    #[test]
    fn both_are_true() {
        task::block_on(async {
            assert_eq!(true, both(future::ready(true), future::ready(true)).await)
        })
    }

    #[test]
    fn left_is_false() {
        task::block_on(async {
            assert_eq!(false, both(future::ready(false), future::ready(true)).await)
        })
    }

    #[test]
    fn right_is_false() {
        task::block_on(async {
            assert_eq!(false, both(future::ready(true), future::ready(false)).await)
        })
    }

    #[test]
    fn both_are_false() {
        task::block_on(async {
            assert_eq!(
                false,
                both(future::ready(false), future::ready(false)).await
            )
        })
    }
}

/// Resolve as true unless any future in the iterator resolves as false.
pub async fn all<I>(i: I) -> bool
where
    I: IntoIterator,
    I::Item: Future<Output = bool>,
{
    let mut s = futures::stream::iter(i).buffer_unordered(64);
    while let Some(r) = s.next().await {
        if !r {
            return false;
        }
    }

    true
}

#[cfg(test)]
mod all_tests {
    use super::all;
    use async_std::task;
    use future::Ready;
    use futures::future;

    #[test]
    fn true_for_empty() {
        task::block_on(async {
            let futures = Vec::<Ready<bool>>::new();
            assert_eq!(true, all(futures).await);
        })
    }

    #[test]
    fn true_if_all_true() {
        task::block_on(async {
            let futures = vec![future::ready(true), future::ready(true)];
            assert_eq!(true, all(futures).await);
        })
    }

    #[test]
    fn false_if_any_false() {
        task::block_on(async {
            assert_eq!(
                false,
                all(vec![future::ready(false), future::ready(true)]).await
            );
            assert_eq!(
                false,
                all(vec![future::ready(true), future::ready(false)]).await
            );
        })
    }
}