itertools/adaptors/
map.rs

1use std::iter::FromIterator;
2use std::marker::PhantomData;
3
4#[derive(Clone, Debug)]
5#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
6pub struct MapSpecialCase<I, F> {
7    iter: I,
8    f: F,
9}
10
11pub trait MapSpecialCaseFn<T> {
12    type Out;
13    fn call(&mut self, t: T) -> Self::Out;
14}
15
16impl<I, R> Iterator for MapSpecialCase<I, R>
17where
18    I: Iterator,
19    R: MapSpecialCaseFn<I::Item>,
20{
21    type Item = R::Out;
22
23    fn next(&mut self) -> Option<Self::Item> {
24        self.iter.next().map(|i| self.f.call(i))
25    }
26
27    fn size_hint(&self) -> (usize, Option<usize>) {
28        self.iter.size_hint()
29    }
30
31    fn fold<Acc, Fold>(self, init: Acc, mut fold_f: Fold) -> Acc
32    where
33        Fold: FnMut(Acc, Self::Item) -> Acc,
34    {
35        let mut f = self.f;
36        self.iter.fold(init, move |acc, v| fold_f(acc, f.call(v)))
37    }
38
39    fn collect<C>(self) -> C
40    where
41        C: FromIterator<Self::Item>,
42    {
43        let mut f = self.f;
44        self.iter.map(move |v| f.call(v)).collect()
45    }
46}
47
48impl<I, R> DoubleEndedIterator for MapSpecialCase<I, R>
49where
50    I: DoubleEndedIterator,
51    R: MapSpecialCaseFn<I::Item>,
52{
53    fn next_back(&mut self) -> Option<Self::Item> {
54        self.iter.next_back().map(|i| self.f.call(i))
55    }
56}
57
58impl<I, R> ExactSizeIterator for MapSpecialCase<I, R>
59where
60    I: ExactSizeIterator,
61    R: MapSpecialCaseFn<I::Item>,
62{
63}
64
65/// An iterator adapter to apply a transformation within a nested `Result::Ok`.
66///
67/// See [`.map_ok()`](crate::Itertools::map_ok) for more information.
68pub type MapOk<I, F> = MapSpecialCase<I, MapSpecialCaseFnOk<F>>;
69
70/// See [`MapOk`].
71#[deprecated(note = "Use MapOk instead", since = "0.10.0")]
72pub type MapResults<I, F> = MapOk<I, F>;
73
74impl<F, T, U, E> MapSpecialCaseFn<Result<T, E>> for MapSpecialCaseFnOk<F>
75where
76    F: FnMut(T) -> U,
77{
78    type Out = Result<U, E>;
79    fn call(&mut self, t: Result<T, E>) -> Self::Out {
80        t.map(|v| self.0(v))
81    }
82}
83
84#[derive(Clone)]
85pub struct MapSpecialCaseFnOk<F>(F);
86
87impl<F> std::fmt::Debug for MapSpecialCaseFnOk<F> {
88    debug_fmt_fields!(MapSpecialCaseFnOk,);
89}
90
91/// Create a new `MapOk` iterator.
92pub fn map_ok<I, F, T, U, E>(iter: I, f: F) -> MapOk<I, F>
93where
94    I: Iterator<Item = Result<T, E>>,
95    F: FnMut(T) -> U,
96{
97    MapSpecialCase {
98        iter,
99        f: MapSpecialCaseFnOk(f),
100    }
101}
102
103/// An iterator adapter to apply `Into` conversion to each element.
104///
105/// See [`.map_into()`](crate::Itertools::map_into) for more information.
106pub type MapInto<I, R> = MapSpecialCase<I, MapSpecialCaseFnInto<R>>;
107
108impl<T: Into<U>, U> MapSpecialCaseFn<T> for MapSpecialCaseFnInto<U> {
109    type Out = U;
110    fn call(&mut self, t: T) -> Self::Out {
111        t.into()
112    }
113}
114
115#[derive(Clone, Debug)]
116pub struct MapSpecialCaseFnInto<U>(PhantomData<U>);
117
118/// Create a new [`MapInto`] iterator.
119pub fn map_into<I, R>(iter: I) -> MapInto<I, R> {
120    MapSpecialCase {
121        iter,
122        f: MapSpecialCaseFnInto(PhantomData),
123    }
124}