Skip to content

Commit 95342cb

Browse files
Add try_map_results method.
1 parent 19eb024 commit 95342cb

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

src/adaptors/mod.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,55 @@ impl<I, F, T, U, E> Iterator for MapResults<I, F>
11591159
}
11601160
}
11611161

1162+
/// An iterator adapter to apply a fallible transformation within a nested `Result`.
1163+
///
1164+
/// See [`.try_map_results()`](../trait.Itertools.html#method.try_map_results) for more information.
1165+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
1166+
pub struct TryMapResults<I, F> {
1167+
iter: I,
1168+
f: F
1169+
}
1170+
1171+
/// Create a new `TryMapResults` iterator.
1172+
pub fn try_map_results<I, F, T, U, E>(iter: I, f: F) -> TryMapResults<I, F>
1173+
where I: Iterator<Item = Result<T, E>>,
1174+
F: FnMut(T) -> Result<U, E>
1175+
{
1176+
TryMapResults {
1177+
iter: iter,
1178+
f: f,
1179+
}
1180+
}
1181+
1182+
impl<I, F, T, U, E> Iterator for TryMapResults<I, F>
1183+
where I: Iterator<Item = Result<T, E>>,
1184+
F: FnMut(T) -> Result<U, E>
1185+
{
1186+
type Item = Result<U, E>;
1187+
1188+
fn next(&mut self) -> Option<Self::Item> {
1189+
self.iter.next().map(|v| v.and_then(&mut self.f))
1190+
}
1191+
1192+
fn size_hint(&self) -> (usize, Option<usize>) {
1193+
self.iter.size_hint()
1194+
}
1195+
1196+
fn fold<Acc, Fold>(self, init: Acc, mut fold_f: Fold) -> Acc
1197+
where Fold: FnMut(Acc, Self::Item) -> Acc,
1198+
{
1199+
let mut f = self.f;
1200+
self.iter.fold(init, move |acc, v| fold_f(acc, v.and_then(&mut f)))
1201+
}
1202+
1203+
fn collect<C>(self) -> C
1204+
where C: FromIterator<Self::Item>
1205+
{
1206+
let mut f = self.f;
1207+
self.iter.map(move |v| v.and_then(&mut f)).collect()
1208+
}
1209+
}
1210+
11621211
/// An iterator adapter to get the positions of each element that matches a predicate.
11631212
///
11641213
/// See [`.positions()`](../trait.Itertools.html#method.positions) for more information.

src/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ pub mod structs {
5959
Batching,
6060
Step,
6161
MapResults,
62+
TryMapResults,
6263
Merge,
6364
MergeBy,
6465
TakeWhileRef,
@@ -635,6 +636,24 @@ pub trait Itertools : Iterator {
635636
adaptors::map_results(self, f)
636637
}
637638

639+
/// Return an iterator adaptor that applies the provided fallible
640+
/// closure to every `Result::Ok` value. `Result::Err` values in
641+
/// the original iterator are unchanged.
642+
///
643+
/// ```
644+
/// use itertools::Itertools;
645+
///
646+
/// let input = vec![Ok(41), Err(false), Ok(i32::max_value())];
647+
/// let it = input.into_iter().try_map_results(|i| i.checked_add(1).ok_or(true));
648+
/// itertools::assert_equal(it, vec![Ok(42), Err(false), Err(true)]);
649+
/// ```
650+
fn try_map_results<F, T, U, E>(self, f: F) -> TryMapResults<Self, F>
651+
where Self: Iterator<Item = Result<T, E>> + Sized,
652+
F: FnMut(T) -> Result<U, E>,
653+
{
654+
adaptors::try_map_results(self, f)
655+
}
656+
638657
/// Return an iterator adaptor that merges the two base iterators in
639658
/// ascending order. If both base iterators are sorted (ascending), the
640659
/// result is sorted.

0 commit comments

Comments
 (0)