#![deny(rustdoc::broken_intra_doc_links)]
use itertools::Itertools;
pub(crate) trait FallibleIterator: Sized + Itertools {
fn fallible_filter<F, E>(self, predicate: F) -> FallibleFilter<Self, F>
where
F: FnMut(&Self::Item) -> Result<bool, E>,
{
FallibleFilter {
iter: self,
predicate,
}
}
fn and_then_filter<T, E, F>(self, predicate: F) -> AndThenFilter<Self, F>
where
Self: Iterator<Item = Result<T, E>>,
F: FnMut(&T) -> Result<bool, E>,
{
AndThenFilter {
iter: self,
predicate,
}
}
fn fallible_all<E, F>(&mut self, mut predicate: F) -> Result<bool, E>
where
F: FnMut(Self::Item) -> Result<bool, E>,
{
let mut digest = true;
for val in self.by_ref() {
digest &= predicate(val)?;
if !digest {
break;
}
}
Ok(digest)
}
fn fallible_any<E, F>(&mut self, mut predicate: F) -> Result<bool, E>
where
F: FnMut(Self::Item) -> Result<bool, E>,
{
let mut digest = false;
for val in self.by_ref() {
digest |= predicate(val)?;
if digest {
break;
}
}
Ok(digest)
}
fn ok_and_any<T, E, F>(&mut self, predicate: F) -> Result<bool, E>
where
Self: Iterator<Item = Result<T, E>>,
F: FnMut(T) -> bool,
{
self.process_results(|mut results| results.any(predicate))
}
fn and_then<T, E, U, F>(self, map: F) -> AndThen<Self, F>
where
Self: Iterator<Item = Result<T, E>>,
F: FnMut(T) -> Result<U, E>,
{
AndThen { iter: self, map }
}
fn find_ok<F, T, E>(&mut self, predicate: F) -> Result<Option<T>, E>
where
Self: Iterator<Item = Result<T, E>>,
F: FnMut(&T) -> bool,
{
self.process_results(|mut results| results.find(predicate))
}
fn fallible_fold<F, O, T, E>(&mut self, mut init: O, mut mapper: F) -> Result<O, E>
where
Self: Iterator<Item = T>,
F: FnMut(O, T) -> Result<O, E>,
{
for item in self {
init = mapper(init, item)?;
}
Ok(init)
}
}
impl<I: Itertools> FallibleIterator for I {}
pub(crate) struct FallibleFilter<I, F> {
iter: I,
predicate: F,
}
impl<I, F, E> Iterator for FallibleFilter<I, F>
where
I: Iterator,
F: FnMut(&I::Item) -> Result<bool, E>,
{
type Item = Result<I::Item, E>;
fn next(&mut self) -> Option<Self::Item> {
loop {
let val = self.iter.next()?;
match (self.predicate)(&val) {
Ok(true) => return Some(Ok(val)),
Ok(false) => {}
Err(e) => return Some(Err(e)),
}
}
}
}
pub(crate) struct AndThenFilter<I, F> {
iter: I,
predicate: F,
}
impl<I, F, T, E> Iterator for AndThenFilter<I, F>
where
I: Iterator<Item = Result<T, E>>,
F: FnMut(&T) -> Result<bool, E>,
{
type Item = Result<T, E>;
fn next(&mut self) -> Option<Self::Item> {
loop {
let val = self.iter.next()?;
return match val {
Err(e) => Some(Err(e)),
Ok(val) => match (self.predicate)(&val) {
Ok(true) => Some(Ok(val)),
Ok(false) => continue,
Err(e) => Some(Err(e)),
},
};
}
}
}
pub(crate) struct AndThen<I, F> {
iter: I,
map: F,
}
impl<I, T, E, U, F> Iterator for AndThen<I, F>
where
I: Iterator<Item = Result<T, E>>,
F: FnMut(T) -> Result<U, E>,
{
type Item = Result<U, E>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|res| res.and_then(&mut self.map))
}
}
#[cfg(test)]
mod tests {
use super::*;
type Item = Result<usize, ()>;
fn is_prime(i: usize) -> Result<bool, ()> {
match i {
0 | 1 => Err(()), 2 | 3 => Ok(true),
_ => Ok(false), }
}
fn is_even(i: usize) -> bool {
i.is_multiple_of(2)
}
#[test]
fn test_fallible_filter() {
let vals = (1..6).fallible_filter(|i| is_prime(*i));
itertools::assert_equal(vals, vec![Err(()), Ok(2), Ok(3)]);
}
#[test]
fn test_and_then_filter() {
let vals = vec![Ok(0), Err(()), Err(()), Ok(3), Ok(4)]
.into_iter()
.and_then_filter(|i| is_prime(*i));
itertools::assert_equal(vals, vec![Err(()), Err(()), Err(()), Ok(3)]);
}
#[test]
fn test_fallible_all() {
assert_eq!(Ok(true), [].into_iter().fallible_all(is_prime));
assert_eq!(Ok(true), (2..4).fallible_all(is_prime));
assert_eq!(Err(()), (1..4).fallible_all(is_prime));
assert_eq!(Ok(false), (2..5).fallible_all(is_prime));
assert_eq!(Err(()), (1..5).fallible_all(is_prime));
}
#[test]
fn test_fallible_any() {
assert_eq!(Ok(false), [].into_iter().fallible_any(is_prime));
assert_eq!(Ok(true), (2..5).fallible_any(is_prime));
assert_eq!(Ok(false), (4..5).fallible_any(is_prime));
assert_eq!(Err(()), (1..4).fallible_any(is_prime));
assert_eq!(Err(()), (1..5).fallible_any(is_prime));
}
#[test]
fn test_ok_and_any() {
let first_values: Vec<Item> = vec![];
let second_values: Vec<Item> = vec![Ok(0), Err(())];
let third_values: Vec<Item> = vec![Ok(1), Ok(3)];
let fourth_values: Vec<Item> = vec![Err(()), Ok(0)];
assert_eq!(Ok(false), first_values.into_iter().ok_and_any(is_even));
assert_eq!(Ok(true), second_values.into_iter().ok_and_any(is_even));
assert_eq!(Ok(false), third_values.into_iter().ok_and_any(is_even));
assert_eq!(Err(()), fourth_values.into_iter().ok_and_any(is_even));
}
}