pub trait FirstErr: Iterator {
// Provided methods
fn first_err_or_else<T, E, O, F>(self, f: F) -> Result<O, E>
where F: FnOnce(&mut FirstErrIter<Self, T, E>) -> O,
Self: Iterator<Item = Result<T, E>> + Sized { ... }
fn first_err_or_try<T, E, O, F>(self, f: F) -> Result<O, E>
where F: FnOnce(&mut FirstErrIter<Self, T, E>) -> Result<O, E>,
Self: Iterator<Item = Result<T, E>> + Sized { ... }
fn first_err_or<T, E, O>(self, value: O) -> Result<O, E>
where Self: Iterator<Item = Result<T, E>> + Sized { ... }
fn first_none_or_else<T, O, F>(self, f: F) -> Option<O>
where F: FnOnce(&mut FirstNoneIter<Self, T>) -> O,
Self: Iterator<Item = Option<T>> + Sized { ... }
fn first_none_or_try<T, O, F>(self, f: F) -> Option<O>
where F: FnOnce(&mut FirstNoneIter<Self, T>) -> Option<O>,
Self: Iterator<Item = Option<T>> + Sized { ... }
fn first_none_or<T, O>(self, value: O) -> Option<O>
where Self: Iterator<Item = Option<T>> + Sized { ... }
}Expand description
This trait provides some methods on any Iterator<Item = Result<T, E>>, which can take
the first Err in iterators, and without allocation.
Iterator<Item = Option<T>> version with the same logic are also supported.
§Guarantees
There are some methods in FirstErr trait take a closure that accepts an iterator
as its argument. This crate guarantees all those methods have the following properties.
§Original Iterator is Evaluated Lazily
The .next() of the original iterator only be called as late as possible, For example,
let mut vec = RefCell::new(vec![]);
let mut result = [Ok::<u8, u8>(0), Ok(1), Err(2), Ok(3)]
.into_iter()
.inspect(|res| { vec.borrow_mut().push(*res) }) // push value from outer
.first_err_or_else(|iter| {
iter
.inspect(|n| { vec.borrow_mut().push(Ok(42)) }) // push value from inner
.sum::<u8>()
});
assert_eq!(result, Err(2));
assert_eq!(
vec.into_inner(),
vec![Ok(0), Ok(42), Ok(1), Ok(42), Err(2)],
);§No Need to Manually Consume the Closure’s Iterator
User can simple ignore the iterator in closure partially of fully, and still can get the correct result.
let result = [Ok::<u8, u8>(0), Err(1), Err(2)]
.into_iter()
.first_err_or_else(|_iter| {}); // not need to consume `_iter` iterator,
assert_eq!(result, Err(1)); // and the result still correct.§Iterator in Closure Can’t be Leaked Out of Closure Scope
Let the iterator in closure escaped from the closure is a compiler error.
let iter = [Ok::<u8, u8>(0), Err(1), Err(2)]
.into_iter()
.first_err_or_else(|iter| iter); // compile error: can't leak `iter` outProvided Methods§
Sourcefn first_err_or_else<T, E, O, F>(self, f: F) -> Result<O, E>
fn first_err_or_else<T, E, O, F>(self, f: F) -> Result<O, E>
Returns the first Err item in the current iterator, or an Ok value produced by the
f closure.
The argument iterator of the f closure will producing the same values in Ok sequence,
but will stop when encounter the first Err item.
§Examples
use first_err::FirstErr;
// Everything is Ok.
let result = [Ok::<u8, u8>(0), Ok(1), Ok(2)]
.into_iter()
.first_err_or_else(|iter| iter.sum::<u8>());
assert_eq!(result, Ok(3));
// Contains some `Err` values.
let result = [Ok::<u8, u8>(0), Err(1), Err(2)]
.into_iter()
.first_err_or_else(|iter| iter.sum::<u8>());
assert_eq!(result, Err(1));Sourcefn first_err_or_try<T, E, O, F>(self, f: F) -> Result<O, E>
fn first_err_or_try<T, E, O, F>(self, f: F) -> Result<O, E>
Returns the first Err item in the current iterator, or an Result value produced
by the f closure.
The argument iterator of the f closure will producing the same values in Ok sequence,
but will stop when encounter the first Err item.
§Examples
Basic concept:
use first_err::FirstErr;
// Everything is Ok.
let result = [Ok::<u8, u8>(0), Ok(1), Ok(2)]
.into_iter()
.first_err_or_try(|_| Ok("ok"));
assert_eq!(result, Ok("ok"));
// When closure returns Err.
let result = [Ok::<u8, u8>(0), Ok(1), Ok(2)]
.into_iter()
.first_err_or_try(|_| Err::<u8, u8>(42));
assert_eq!(result, Err(42));
// When outer iterator contains Err.
let result = [Ok::<u8, u8>(0), Err(2), Ok(2)]
.into_iter()
.first_err_or_try(|_| Ok("ok"));
assert_eq!(result, Err(2));
// When both contains Err.
let result = [Ok::<u8, u8>(0), Err(1), Ok(2)]
.into_iter()
.first_err_or_try(|_| Err::<u8, u8>(42));
assert_eq!(result, Err(1));Use the iter argument of the f closure:
let admin_id: u32 = 1;
let user_ids_in_conf = ["32", "5", "8", "19"];
let admin_index = user_ids_in_conf
.into_iter()
.map(|s| s.parse::<u32>().map_err(|_| "user id parsing failed"))
.first_err_or_try(|user_ids_iter| {
user_ids_iter
.position(|user_id| user_id == admin_id)
.ok_or_else(|| "admin not in the user list")
});
assert_eq!(admin_index, Err("admin not in the user list"));Sourcefn first_err_or<T, E, O>(self, value: O) -> Result<O, E>
fn first_err_or<T, E, O>(self, value: O) -> Result<O, E>
Returns the first Err item in the current iterator, or an Ok(value).
§Examples
// Everything is Ok.
let result = [Ok::<u8, u8>(0), Ok(1), Ok(2)]
.into_iter()
.first_err_or("foo");
assert_eq!(result, Ok("foo"));
// Contains some `Err` values.
let result = [Ok::<u8, u8>(0), Err(1), Err(2)]
.into_iter()
.first_err_or("foo");
assert_eq!(result, Err(1));Sourcefn first_none_or_else<T, O, F>(self, f: F) -> Option<O>
fn first_none_or_else<T, O, F>(self, f: F) -> Option<O>
Returns the first None item in the current iterator, or an Some value produced
by the f closure.
The argument iterator of the f closure will producing the same values in Some sequence,
but will stop when encounter the first None item.
§Examples
use first_err::FirstErr;
// Everything is Some.
let option = [Some::<u8>(0), Some(1), Some(2)]
.into_iter()
.first_none_or_else(|iter| iter.sum::<u8>());
assert_eq!(option, Some(3));
// Contains some `None` values.
let option = [Some::<u8>(0), None, None]
.into_iter()
.first_none_or_else(|iter| iter.sum::<u8>());
assert_eq!(option, None);Sourcefn first_none_or_try<T, O, F>(self, f: F) -> Option<O>
fn first_none_or_try<T, O, F>(self, f: F) -> Option<O>
Returns the first None item in the current iterator, or an Option value produced
by the f closure.
The argument iterator of the f closure will producing the same values in Some sequence,
but will stop when encounter the first None item.
§Examples
Basic concept:
use first_err::FirstErr;
// Everything is Some.
let option = [Some::<u8>(0), Some(1), Some(2)]
.into_iter()
.first_none_or_try(|_| Some("ok"));
assert_eq!(option, Some("ok"));
// When closure returns None.
let option: Option<&str> = [Some::<u8>(0), Some(1), Some(2)]
.into_iter()
.first_none_or_try(|_| None);
assert_eq!(option, None);
// When outer iterator contains None.
let option = [Some::<u8>(0), None, Some(2)]
.into_iter()
.first_none_or_try(|_| Some("ok"));
assert_eq!(option, None);
// When both contains None.
let option: Option<&str> = [Some::<u8>(0), None, Some(2)]
.into_iter()
.first_none_or_try(|_| None);
assert_eq!(option, None);Use the iter argument of the f closure:
let admin_id: u32 = 1;
let user_ids_in_conf = ["32", "5", "8", "19"];
let admin_index = user_ids_in_conf
.into_iter()
.map(|s| s.parse::<u32>().ok())
.first_none_or_try(|user_ids_iter| {
user_ids_iter
.position(|user_id| user_id == admin_id)
});
assert_eq!(admin_index, None);Sourcefn first_none_or<T, O>(self, value: O) -> Option<O>
fn first_none_or<T, O>(self, value: O) -> Option<O>
Returns the first None item in the current iterator, or an Some(value).
§Examples
// Everything is Some.
let option = [Some::<u8>(0), Some(1), Some(2)]
.into_iter()
.first_none_or("foo");
assert_eq!(option, Some("foo"));
// Contains some `None` values.
let option = [Some::<u8>(0), None, None]
.into_iter()
.first_none_or("foo");
assert_eq!(option, None);