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}