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    pub(crate) iter: I,
8    pub(crate) 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
70impl<F, T, U, E> MapSpecialCaseFn<Result<T, E>> for MapSpecialCaseFnOk<F>
71where
72    F: FnMut(T) -> U,
73{
74    type Out = Result<U, E>;
75    fn call(&mut self, t: Result<T, E>) -> Self::Out {
76        t.map(|v| self.0(v))
77    }
78}
79
80#[derive(Clone)]
81pub struct MapSpecialCaseFnOk<F>(F);
82
83impl<F> std::fmt::Debug for MapSpecialCaseFnOk<F> {
84    debug_fmt_fields!(MapSpecialCaseFnOk,);
85}
86
87/// Create a new `MapOk` iterator.
88pub fn map_ok<I, F, T, U, E>(iter: I, f: F) -> MapOk<I, F>
89where
90    I: Iterator<Item = Result<T, E>>,
91    F: FnMut(T) -> U,
92{
93    MapSpecialCase {
94        iter,
95        f: MapSpecialCaseFnOk(f),
96    }
97}
98
99/// An iterator adapter to apply `Into` conversion to each element.
100///
101/// See [`.map_into()`](crate::Itertools::map_into) for more information.
102pub type MapInto<I, R> = MapSpecialCase<I, MapSpecialCaseFnInto<R>>;
103
104impl<T: Into<U>, U> MapSpecialCaseFn<T> for MapSpecialCaseFnInto<U> {
105    type Out = U;
106    fn call(&mut self, t: T) -> Self::Out {
107        t.into()
108    }
109}
110
111pub struct MapSpecialCaseFnInto<U>(PhantomData<U>);
112
113impl<U> std::fmt::Debug for MapSpecialCaseFnInto<U> {
114    debug_fmt_fields!(MapSpecialCaseFnInto, 0);
115}
116
117impl<U> Clone for MapSpecialCaseFnInto<U> {
118    #[inline]
119    fn clone(&self) -> Self {
120        Self(PhantomData)
121    }
122}
123
124/// Create a new [`MapInto`] iterator.
125pub fn map_into<I, R>(iter: I) -> MapInto<I, R> {
126    MapSpecialCase {
127        iter,
128        f: MapSpecialCaseFnInto(PhantomData),
129    }
130}