diff --git a/benches/specializations.rs b/benches/specializations.rs index 958bcc124..3a5d80326 100644 --- a/benches/specializations.rs +++ b/benches/specializations.rs @@ -648,6 +648,7 @@ bench_specializations! { v.iter().copied().filter_ok(|x| x % 3 == 0) } filter_map_ok { + DoubleEndedIterator { let v = black_box((0_u32..1024) .map(|x| if x % 2 == 1 { Err(x) } else { Ok(x) }) diff --git a/src/adaptors/mod.rs b/src/adaptors/mod.rs index e757837b7..095b08918 100644 --- a/src/adaptors/mod.rs +++ b/src/adaptors/mod.rs @@ -1041,6 +1041,30 @@ where } } +impl<I, F, T, U, E> DoubleEndedIterator for FilterMapOk<I, F> +where + I: DoubleEndedIterator<Item = Result<T, E>>, + F: FnMut(T) -> Option<U>, +{ + fn next_back(&mut self) -> Option<Self::Item> { + let f = &mut self.f; + self.iter.by_ref().rev().find_map(|res| match res { + Ok(t) => f(t).map(Ok), + Err(e) => Some(Err(e)), + }) + } + + fn rfold<Acc, Fold>(self, init: Acc, fold_f: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter + .filter_map(|v| transpose_result(v.map(&mut f))) + .rfold(init, fold_f) + } +} + impl<I, F, T, U, E> FusedIterator for FilterMapOk<I, F> where I: FusedIterator<Item = Result<T, E>>, diff --git a/tests/specializations.rs b/tests/specializations.rs index cdc51fb23..ff3d5c19b 100644 --- a/tests/specializations.rs +++ b/tests/specializations.rs @@ -453,7 +453,9 @@ quickcheck! { } fn filter_map_ok(v: Vec<Result<u8, char>>) -> () { - test_specializations(&v.into_iter().filter_map_ok(|i| if i < 20 { Some(i * 2) } else { None })); + let it = v.into_iter().filter_map_ok(|i| if i < 20 { Some(i * 2) } else { None }); + test_specializations(&it); + test_double_ended_specializations(&it); } // `SmallIter2<u8>` because `Vec<u8>` is too slow and we get bad coverage from a singleton like Option<u8>