You can implement these iterators yourself. See how filter and map are implemented in the standard library.
map_ok
implementation:
#[derive(Clone)]
pub struct MapOkIterator {
iter: I,
f: F,
}
impl Iterator for MapOkIterator
where
F: FnMut(A) -> B,
I: Iterator- >,
{
type Item = Result;
#[inline]
fn next(&mut self) -> Option {
self.iter.next().map(|x| x.map(&mut self.f))
}
}
pub trait MapOkTrait {
fn map_ok(self, func: F) -> MapOkIterator
where
Self: Sized + Iterator
- >,
F: FnMut(A) -> B,
{
MapOkIterator {
iter: self,
f: func,
}
}
}
impl MapOkTrait for I
where
I: Sized + Iterator
- >,
{
}
filter_ok
is almost the same:
#[derive(Clone)]
pub struct FilterOkIterator {
iter: I,
predicate: P,
}
impl Iterator for FilterOkIterator
where
P: FnMut(&A) -> bool,
I: Iterator- >,
{
type Item = Result;
#[inline]
fn next(&mut self) -> Option> {
for x in self.iter.by_ref() {
match x {
Ok(xx) => if (self.predicate)(&xx) {
return Some(Ok(xx));
},
Err(_) => return Some(x),
}
}
None
}
}
pub trait FilterOkTrait {
fn filter_ok
(self, predicate: P) -> FilterOkIterator
where
Self: Sized + Iterator- >,
P: FnMut(&A) -> bool,
{
FilterOkIterator {
iter: self,
predicate: predicate,
}
}
}
impl FilterOkTrait for I
where
I: Sized + Iterator
- >,
{
}
Your code may look like this:
["1", "2", "3", "4"]
.iter()
.map(|x| x.parse::().map(|a| a + 10))
.filter_ok(|x| x % 2 == 0)
.map_ok(|x| x + 100)
.collect::, std::num::ParseIntError>>()
playground