#![no_std]
pub use option::FirstNoneIter;
pub use result::FirstErrIter;
pub trait FirstErr: Iterator {
#[inline]
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,
{
FirstErrIter::first_err_or_else(self, f)
}
#[inline]
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,
{
self.first_err_or_else(f).and_then(|res| res)
}
#[inline]
fn first_err_or<T, E, O>(self, value: O) -> Result<O, E>
where
Self: Iterator<Item = Result<T, E>> + Sized,
{
self.first_err_or_else(|_| value)
}
#[inline]
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,
{
FirstNoneIter::first_none_or_else(self, f)
}
#[inline]
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,
{
self.first_none_or_else(f).and_then(|opt| opt)
}
#[inline]
fn first_none_or<T, O>(self, value: O) -> Option<O>
where
Self: Iterator<Item = Option<T>> + Sized,
{
self.first_none_or_else(|_| value)
}
}
impl<I> FirstErr for I where I: Iterator {}
mod result {
use core::iter::FusedIterator;
#[derive(Debug)]
pub struct FirstErrIter<I, T, E>
where
I: Iterator<Item = Result<T, E>>,
{
state: State<I, T, E>,
}
impl<I, T, E> FirstErrIter<I, T, E>
where
I: Iterator<Item = Result<T, E>>,
{
#[inline]
pub(super) fn first_err_or_else<O, F>(inner: I, f: F) -> Result<O, E>
where
F: FnOnce(&mut Self) -> O,
{
let mut me = Self {
state: State::Active(inner),
};
let output = f(&mut me);
match me.state {
State::Active(inner) => {
for res in inner {
let _ = res?;
}
Ok(output)
}
State::Exhausted => Ok(output),
State::FoundFirstErr(e) => Err(e),
}
}
}
impl<I, T, E> Iterator for FirstErrIter<I, T, E>
where
I: Iterator<Item = Result<T, E>>,
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match &mut self.state {
State::Active(inner) => match inner.next() {
Some(Ok(t)) => Some(t),
Some(Err(e)) => {
self.state = State::FoundFirstErr(e);
None
}
None => {
self.state = State::Exhausted;
None
}
},
State::FoundFirstErr(_) => None,
State::Exhausted => None,
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match &self.state {
State::Active(inner) => inner.size_hint(),
State::FoundFirstErr(_) => (0, Some(0)),
State::Exhausted => (0, Some(0)),
}
}
}
impl<I, T, E> FusedIterator for FirstErrIter<I, T, E> where I: Iterator<Item = Result<T, E>> {}
#[derive(Debug)]
enum State<I, T, E>
where
I: Iterator<Item = Result<T, E>>,
{
Active(I),
FoundFirstErr(E),
Exhausted,
}
}
mod option {
use core::iter::FusedIterator;
#[derive(Debug)]
pub struct FirstNoneIter<I, T>
where
I: Iterator<Item = Option<T>>,
{
state: State<I, T>,
}
impl<I, T> FirstNoneIter<I, T>
where
I: Iterator<Item = Option<T>>,
{
#[inline]
pub(super) fn first_none_or_else<O, F>(inner: I, f: F) -> Option<O>
where
F: FnOnce(&mut Self) -> O,
{
let mut me = Self {
state: State::Active(inner),
};
let output = f(&mut me);
match me.state {
State::Active(inner) => {
for opt in inner {
let _ = opt?;
}
Some(output)
}
State::Exhausted => Some(output),
State::FoundFirstNone => None,
}
}
}
impl<I, T> Iterator for FirstNoneIter<I, T>
where
I: Iterator<Item = Option<T>>,
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match &mut self.state {
State::Active(inner) => match inner.next() {
Some(Some(t)) => Some(t),
Some(None) => {
self.state = State::FoundFirstNone;
None
}
None => {
self.state = State::Exhausted;
None
}
},
State::FoundFirstNone => None,
State::Exhausted => None,
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match &self.state {
State::Active(inner) => inner.size_hint(),
State::FoundFirstNone => (0, Some(0)),
State::Exhausted => (0, Some(0)),
}
}
}
impl<I, T> FusedIterator for FirstNoneIter<I, T> where I: Iterator<Item = Option<T>> {}
#[derive(Debug)]
enum State<I, T>
where
I: Iterator<Item = Option<T>>,
{
Active(I),
FoundFirstNone,
Exhausted,
}
}
#[cfg(test)]
mod tests {
mod test_first_err {
use crate::FirstErr;
#[test]
fn _or_else_with_1_layer_data_and_without_err() {
let ans = [Ok::<u8, u8>(0), Ok(1), Ok(2), Ok(3), Ok(4)]
.into_iter()
.first_err_or_else(|iter1| iter1.sum::<u8>());
assert_eq!(ans, Ok(10));
}
#[test]
fn _or_else_with_1_layer_data_and_with_err() {
let ans = [Ok::<u8, u8>(0), Ok(1), Err(2), Ok(3), Ok(4)]
.into_iter()
.first_err_or_else(|iter1| iter1.sum::<u8>());
assert_eq!(ans, Err(2));
}
#[test]
fn _or_else_with_2_layer_data_and_outmost_err_in_layer_1() {
let ans = [
Ok::<Result<u8, u8>, u8>(Ok(0)),
Ok(Err(1)),
Err(2),
Ok(Ok(3)),
Ok(Ok(4)),
]
.into_iter()
.first_err_or_else(|iter1| {
iter1
.first_err_or_else(|iter2| iter2.sum::<u8>())
});
assert_eq!(ans, Err(2));
}
#[test]
fn _or_else_with_2_layer_data_and_outmost_err_in_layer_2() {
let ans = [
Ok::<Result<u8, u8>, u8>(Ok(0)),
Ok(Ok(1)),
Ok(Err(2)),
Ok(Err(3)),
Ok(Ok(4)),
]
.into_iter()
.first_err_or_else(|iter1| {
iter1
.first_err_or_else(|iter2| iter2.sum::<u8>())
});
assert_eq!(ans, Ok(Err(2)));
}
#[test]
fn _or_else_with_3_layer_data_and_outmost_err_in_layer_2() {
let ans = [
Ok::<Result<Result<u8, u8>, u8>, u8>(Ok(Ok(0))),
Ok(Ok(Ok(1))),
Ok(Ok(Err(2))),
Ok(Err(3)),
Ok(Ok(Ok(4))),
]
.into_iter()
.first_err_or_else(|iter1| {
iter1
.first_err_or_else(|iter2| {
iter2
.first_err_or_else(|iter3| iter3.sum::<u8>())
})
});
assert_eq!(ans, Ok(Err(3)));
}
#[test]
fn _or_else_not_need_to_consume_iter_manually() {
let ans = [Ok::<u8, u8>(0), Err(1), Err(2)]
.into_iter()
.first_err_or_else(|_iter| {});
assert_eq!(ans, Err(1));
}
#[test]
fn _or_else_never_call_next_on_orig_iter_after_first_err_found() {
let mut orig_iter_next_count = 0;
[Ok::<u8, u8>(0), Err(1), Err(2)]
.into_iter()
.inspect(|_| orig_iter_next_count += 1) .first_err_or_else(|iter| {
for _ in &mut *iter {}
assert_eq!(iter.next(), None);
})
.ok();
assert_eq!(orig_iter_next_count, 2);
}
#[test]
fn _or_else_use_lazy_evaluation() {
use core::cell::{Cell, RefCell};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Trace {
None,
Outer(Result<u8, u8>),
Inner(u8),
}
fn record_trace<const N: usize>(
traces: &RefCell<[Trace; N]>,
idx: &Cell<usize>,
v: Trace,
) {
let i = idx.get();
traces.borrow_mut()[i] = v;
idx.set(i + 1);
}
let traces = RefCell::new([Trace::None; 5]);
let index = Cell::new(0);
let ans = [Ok::<u8, u8>(0), Ok(1), Err(2), Ok(3)]
.iter()
.cloned()
.inspect(|&res| record_trace(&traces, &index, Trace::Outer(res)))
.first_err_or_else(|iter| {
iter
.inspect(|&n| record_trace(&traces, &index, Trace::Inner(n)))
.sum::<u8>()
});
assert_eq!(ans, Err(2));
assert_eq!(
traces.into_inner(),
[
Trace::Outer(Ok(0)),
Trace::Inner(0),
Trace::Outer(Ok(1)),
Trace::Inner(1),
Trace::Outer(Err(2))
]
);
}
#[test]
fn _or_else_with_non_fused_iterator() {
struct NonFusedIter {
curr: u32,
}
impl NonFusedIter {
fn new() -> Self {
Self { curr: 0 }
}
}
impl Iterator for NonFusedIter {
type Item = Result<u32, u32>;
fn next(&mut self) -> Option<Self::Item> {
let tmp = self.curr;
self.curr += 1;
match tmp % 3 {
0 => Some(Ok(tmp)),
1 => None,
2 => Some(Err(tmp)),
_ => unreachable!(),
}
}
}
let ans = NonFusedIter::new().first_err_or_else(|iter| iter.sum::<u32>());
assert_eq!(ans, Ok(0));
}
#[test]
fn _or_without_err() {
let ans = [Ok::<u8, u8>(0), Ok(1), Ok(2), Ok(3), Ok(4)]
.into_iter()
.first_err_or("no err");
assert_eq!(ans, Ok("no err"));
}
#[test]
fn _or_with_err() {
let ans = [Ok::<u8, u8>(0), Ok(1), Err(2), Ok(3), Ok(4)]
.into_iter()
.first_err_or("no err");
assert_eq!(ans, Err(2));
}
#[test]
fn _or_try_without_err_and_closure_produce_ok() {
let ans = [Ok::<u8, u8>(0), Ok(1), Ok(2), Ok(3), Ok(4)]
.into_iter()
.first_err_or_try(|iter| iter.nth(1).ok_or(1));
assert_eq!(ans, Ok(1));
}
#[test]
fn _or_try_without_err_and_closure_produce_err() {
let ans = [Ok::<u8, u8>(0), Ok(1), Ok(2), Ok(3), Ok(4)]
.into_iter()
.first_err_or_try(|iter| iter.nth(100).ok_or(100));
assert_eq!(ans, Err(100));
}
#[test]
fn _or_try_with_err_and_closure_produce_ok() {
let ans = [Ok::<u8, u8>(0), Ok(1), Err(2), Ok(3), Ok(4)]
.into_iter()
.first_err_or_try(|iter| iter.nth(1).ok_or(1));
assert_eq!(ans, Err(2));
}
#[test]
fn _or_try_with_err_and_closure_produce_err() {
let ans = [Ok::<u8, u8>(0), Ok(1), Err(2), Ok(3), Ok(4)]
.into_iter()
.first_err_or_try(|iter| iter.nth(100).ok_or(100));
assert_eq!(ans, Err(2));
}
#[test]
fn _methods_can_call_through_trait_object() {
let mut array_iter = [Ok::<u8, u8>(0), Err(1), Err(2)].into_iter();
fn take_dyn(iter: &mut dyn Iterator<Item = Result<u8, u8>>) {
iter.first_err_or_else(|iter| iter.sum::<u8>()).ok();
iter.first_err_or(0).ok();
iter.first_err_or_try(|iter| Ok(iter.sum::<u8>())).ok();
}
take_dyn(&mut array_iter);
}
}
mod test_first_none {
use crate::FirstErr;
#[test]
fn _or_else_with_1_layer_data_and_without_none() {
let ans = [Some(0u8), Some(1), Some(2), Some(3), Some(4)]
.into_iter()
.first_none_or_else(|iter1| iter1.sum::<u8>());
assert_eq!(ans, Some(10));
}
#[test]
fn _or_else_with_1_layer_data_and_with_none() {
let ans = [Some(0u8), Some(1), None, Some(3), Some(4)]
.into_iter()
.first_none_or_else(|iter1| iter1.sum::<u8>());
assert_eq!(ans, None);
}
#[test]
fn _or_else_with_2_layer_data_and_outmost_none_in_layer_1() {
let ans = [
Some(Some(0u8)),
Some(None),
None,
Some(Some(3)),
Some(Some(4)),
]
.into_iter()
.first_none_or_else(|iter1| {
iter1
.first_none_or_else(|iter2| iter2.sum::<u8>())
});
assert_eq!(ans, None);
}
#[test]
fn _or_else_with_2_layer_data_and_outmost_none_in_layer_2() {
let ans = [
Some(Some(0u8)),
Some(Some(1)),
Some(None),
Some(Some(3)),
Some(Some(4)),
]
.into_iter()
.first_none_or_else(|iter1| {
iter1
.first_none_or_else(|iter2| iter2.sum::<u8>())
});
assert_eq!(ans, Some(None));
}
#[test]
fn _or_else_with_3_layer_data_and_outmost_none_in_layer_2() {
let ans = [
Some(Some(Some(0))),
Some(Some(Some(1))),
Some(Some(None)),
Some(None),
Some(Some(Some(4))),
]
.into_iter()
.first_none_or_else(|iter1| {
iter1
.first_none_or_else(|iter2| {
iter2
.first_none_or_else(|iter3| iter3.sum::<u8>())
})
});
assert_eq!(ans, Some(None));
}
#[test]
fn _or_else_not_need_to_consume_iter_manually() {
let ans = [Some(0), None, None]
.into_iter()
.first_none_or_else(|_iter| {});
assert_eq!(ans, None);
}
#[test]
fn _or_else_never_call_next_on_orig_iter_after_first_none_found() {
let mut orig_iter_next_count = 0;
[Some(0), None, None]
.into_iter()
.inspect(|_| orig_iter_next_count += 1) .first_none_or_else(|iter| {
for _ in &mut *iter {}
assert_eq!(iter.next(), None);
});
assert_eq!(orig_iter_next_count, 2);
}
#[test]
fn _or_else_use_lazy_evaluation() {
use core::cell::{Cell, RefCell};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Trace {
None,
Outer(Option<u8>),
Inner(u8),
}
fn record_trace<const N: usize>(
traces: &RefCell<[Trace; N]>,
idx: &Cell<usize>,
v: Trace,
) {
let i = idx.get();
traces.borrow_mut()[i] = v;
idx.set(i + 1);
}
let traces = RefCell::new([Trace::None; 5]);
let index = Cell::new(0);
let ans = [Some(0u8), Some(1), None, Some(3)]
.iter()
.cloned()
.inspect(|&opt| record_trace(&traces, &index, Trace::Outer(opt)))
.first_none_or_else(|iter| {
iter
.inspect(|&n| record_trace(&traces, &index, Trace::Inner(n)))
.sum::<u8>()
});
assert_eq!(ans, None);
assert_eq!(
traces.into_inner(),
[
Trace::Outer(Some(0)),
Trace::Inner(0),
Trace::Outer(Some(1)),
Trace::Inner(1),
Trace::Outer(None)
]
);
}
#[test]
fn _or_else_with_non_fused_iterator() {
struct NonFusedIter {
curr: u32,
}
impl NonFusedIter {
fn new() -> Self {
Self { curr: 0 }
}
}
impl Iterator for NonFusedIter {
type Item = Option<u32>;
fn next(&mut self) -> Option<Self::Item> {
let tmp = self.curr;
self.curr += 1;
match tmp % 3 {
0 => Some(Some(tmp)),
1 => None, 2 => Some(None), _ => unreachable!(),
}
}
}
let ans = NonFusedIter::new().first_none_or_else(|iter| iter.sum::<u32>());
assert_eq!(ans, Some(0));
}
#[test]
fn _or_without_none() {
let ans = [Some(0u8), Some(1), Some(2), Some(3), Some(4)]
.into_iter()
.first_none_or("no none");
assert_eq!(ans, Some("no none"));
}
#[test]
fn _or_with_none() {
let ans = [Some(0u8), Some(1), None, Some(3), Some(4)]
.into_iter()
.first_none_or("no none");
assert_eq!(ans, None);
}
#[test]
fn _or_try_without_none_and_closure_produce_some() {
let ans = [Some(0u8), Some(1), Some(2), Some(3), Some(4)]
.into_iter()
.first_none_or_try(|iter| iter.nth(1));
assert_eq!(ans, Some(1));
}
#[test]
fn _or_try_without_none_and_closure_produce_none() {
let ans = [Some(0u8), Some(1), Some(2), Some(3), Some(4)]
.into_iter()
.first_none_or_try(|iter| iter.nth(100));
assert_eq!(ans, None);
}
#[test]
fn _or_try_with_none_and_closure_produce_some() {
let ans = [Some(0u8), Some(1), None, Some(3), Some(4)]
.into_iter()
.first_none_or_try(|iter| iter.nth(1));
assert_eq!(ans, None);
}
#[test]
fn _or_try_with_none_and_closure_produce_none() {
let ans = [Some(0u8), Some(1), None, Some(3), Some(4)]
.into_iter()
.first_none_or_try(|iter| iter.nth(100));
assert_eq!(ans, None);
}
#[test]
fn _methods_can_call_through_trait_object() {
let mut array_iter = [Some(0u8), None, None].into_iter();
fn take_dyn(iter: &mut dyn Iterator<Item = Option<u8>>) {
iter.first_none_or_else(|iter| iter.sum::<u8>());
iter.first_none_or(0);
iter.first_none_or_try(|iter| Some(iter.sum::<u8>()));
}
take_dyn(&mut array_iter);
}
}
}