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
#![warn(missing_docs, trivial_casts, trivial_numeric_casts)]
//! Crate for collecting an iterator of results into a result of a collection
//!
//! Special thanks to [elyatai](https://github.com/elyatai) for the idea for this project.

use std::iter::{
    FromIterator,
    Extend,
    once,
    empty
};

mod size_hint_iter;
pub use size_hint_iter::SizeHintedIter;

/// Short circuiting collect of an iterator
pub trait CollectResult<T, E> {
    /// Collects into a result from the iterator
    fn collect_result<O: FromIterator<T> + Extend<T>>(self) -> Result<O, E>;
}

impl<T, E, I: Iterator<Item=Result<T, E>>> CollectResult<T, E> for I {
    /// Takes an iterator of results and tries to collect all `Ok`s from it
    ///
    /// Returns the Err if an item is ever `Err` short-circuting.
    /// That is, it will immediately return the error when it encounters the first one.
    fn collect_result<O: FromIterator<T> + Extend<T>>(self) -> Result<O, E> {
        let (mut lower, mut upper) = self.size_hint();
        let mut ret: O = empty().collect();

        for element in self {
            let iter = SizeHintedIter::with_bounds(once(element?), lower, upper);
            ret.extend(iter);

            lower = lower.saturating_sub(1);
            if let Some(ref mut upper) = upper {
                *upper = upper.saturating_sub(1);
            }
        }

        Ok(ret)
    }
}