async_std/result/
from_stream.rs

1use std::pin::Pin;
2
3use crate::prelude::*;
4use crate::stream::{FromStream, IntoStream};
5
6impl<T, E, V> FromStream<Result<T, E>> for Result<V, E>
7where
8    V: FromStream<T>,
9{
10    /// Takes each element in the stream: if it is an `Err`, no further
11    /// elements are taken, and the `Err` is returned. Should no `Err`
12    /// occur, a container with the values of each `Result` is returned.
13    ///
14    /// # Examples
15    ///
16    /// ```
17    /// # fn main() { async_std::task::block_on(async {
18    /// #
19    /// use async_std::prelude::*;
20    /// use async_std::stream;
21    ///
22    /// let v = stream::from_iter(vec![1, 2]);
23    /// let res: Result<Vec<u32>, &'static str> = v.map(|x: u32|
24    ///     x.checked_add(1).ok_or("Overflow!")
25    /// ).collect().await;
26    /// assert_eq!(res, Ok(vec![2, 3]));
27    /// #
28    /// # }) }
29    /// ```
30    #[inline]
31    fn from_stream<'a, S: IntoStream<Item = Result<T, E>> + 'a>(
32        stream: S,
33    ) -> Pin<Box<dyn Future<Output = Self> + 'a>> {
34        let stream = stream.into_stream();
35
36        Box::pin(async move {
37            // Using `take_while` here because it is able to stop the stream early
38            // if a failure occurs
39            let mut is_error = false;
40            let mut found_error = None;
41            let out: V = stream
42                .take_while(|elem| {
43                    // Stop processing the stream on `Err`
44                    !is_error
45                        && (elem.is_ok() || {
46                            is_error = true;
47                            // Capture first `Err`
48                            true
49                        })
50                })
51                .filter_map(|elem| match elem {
52                    Ok(value) => Some(value),
53                    Err(err) => {
54                        found_error = Some(err);
55                        None
56                    }
57                })
58                .collect()
59                .await;
60
61            if is_error {
62                Err(found_error.unwrap())
63            } else {
64                Ok(out)
65            }
66        })
67    }
68}