Trait TryCollectOrStash

Source
pub trait TryCollectOrStash<T, E, S, I>
where E: Into<I>,
{ // Required method fn try_collect_or_stash<C>(self, stash: &mut S) -> StashedResult<'_, C, I> where C: FromIterator<T>; }
Expand description

Adds the try_collect_or_stash method on Iterator<Item = Result<T, E>> if E implements Into<I>.

Do not implement this trait. Importing the trait is sufficient due to blanket implementations. The trait is implemented automatically if E implements Into<I>, where I is the inner error type, typically prelude::Stashable.

Required Methods§

Source

fn try_collect_or_stash<C>(self, stash: &mut S) -> StashedResult<'_, C, I>
where C: FromIterator<T>,

Counterpart to Iterator::try_collect from the Rust standard library that will not short-circuit, but instead move all Err items into an error stash.

This method evaluates all items in the Iterator. Each time an Err value is encountered, it will be put into the supplied error stash and iteration will continue with the next item.

This method will return a StashedResult::Ok containing a collection of all Result::Ok items. If there are one or more Result::Err items, all of them will be added to the supplied error stash, and this method will return a StashedResult::Err containing that error stash instead.

#[cfg(any(feature = "rust-v1.81", feature = "std"))]
use lazy_errors::{prelude::*, Result};

#[cfg(not(any(feature = "rust-v1.81", feature = "std")))]
use lazy_errors::surrogate_error_trait::{prelude::*, Result};

fn parse_each_u8(tokens: &[&str]) -> Result<Vec<u8>> {
    let mut errs = ErrorStash::new(|| "There were one or more errors");

    let numbers: StashedResult<Vec<u8>> = tokens
        .iter()
        .map(|&s| u8::from_str(s))
        .try_collect_or_stash(&mut errs);

    let numbers: Vec<u8> = try2!(numbers);
    Ok(numbers)
}

let empty = parse_each_u8(&[]).unwrap();
let numbers = parse_each_u8(&["1", "42", "3"]).unwrap();
let errors_1 = parse_each_u8(&["1", "X", "3"]).unwrap_err();
let errors_2 = parse_each_u8(&["1", "X", "Y"]).unwrap_err();
let errors_3 = parse_each_u8(&["X", "Y", "Z"]).unwrap_err();

assert_eq!(&empty, &[]);
assert_eq!(&numbers, &[1, 42, 3]);
assert_eq!(errors_1.children().len(), 1);
assert_eq!(errors_2.children().len(), 2);
assert_eq!(errors_3.children().len(), 3);

Note that Err will only be returned if the iterator contains an Err element. Errors that have been added to the error stash before calling try_collect_or_stash will not be considered. You can call ErrorStash::ok if you want to bail in case of earlier errors as well:

#[cfg(any(feature = "rust-v1.81", feature = "std"))]
use lazy_errors::{prelude::*, Result};

#[cfg(not(any(feature = "rust-v1.81", feature = "std")))]
use lazy_errors::surrogate_error_trait::{prelude::*, Result};

let mut errs = ErrorStash::new(|| "There were one or more errors");

errs.push("Earlier error"); // Ignored in `try_collect_or_stash`

assert!(matches!(errs.ok(), StashedResult::Err(_)));

let numbers = ["42"]
    .iter()
    .map(|&s| u8::from_str(s))
    .try_collect_or_stash::<Vec<u8>>(&mut errs);

assert!(matches!(&numbers, StashedResult::Ok(_)));

let numbers = numbers.ok().unwrap();
assert_eq!(&numbers, &[42]);

assert!(matches!(errs.ok(), StashedResult::Err(_)));

If you need to transform an Iterator<Item = Result<T, E>> into an Iterator<Item = T> and call a method before collecting all T items, take a look at stash_err.

If you want to map elements of a fixed-size array in a similar manner, take a look at try_map_or_stash.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl<Iter, T, E, S, I> TryCollectOrStash<T, E, S, I> for Iter
where Iter: Iterator<Item = Result<T, E>>, E: Into<I>, S: ErrorSource<I> + EnforceErrors<I>, Error<I>: Into<I>, Result<T, Error<I>>: OrStash<S, I, T>,