]> git.lizzy.rs Git - rust.git/blob - library/core/src/iter/adapters/map.rs
Split iterator adaptors into individual modules
[rust.git] / library / core / src / iter / adapters / map.rs
1 use crate::{
2     fmt,
3     iter::{
4         adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess},
5         FusedIterator, InPlaceIterable, TrustedLen,
6     },
7     ops::Try,
8 };
9
10 /// An iterator that maps the values of `iter` with `f`.
11 ///
12 /// This `struct` is created by the [`map`] method on [`Iterator`]. See its
13 /// documentation for more.
14 ///
15 /// [`map`]: Iterator::map
16 /// [`Iterator`]: trait.Iterator.html
17 ///
18 /// # Notes about side effects
19 ///
20 /// The [`map`] iterator implements [`DoubleEndedIterator`], meaning that
21 /// you can also [`map`] backwards:
22 ///
23 /// ```rust
24 /// let v: Vec<i32> = vec![1, 2, 3].into_iter().map(|x| x + 1).rev().collect();
25 ///
26 /// assert_eq!(v, [4, 3, 2]);
27 /// ```
28 ///
29 /// [`DoubleEndedIterator`]: trait.DoubleEndedIterator.html
30 ///
31 /// But if your closure has state, iterating backwards may act in a way you do
32 /// not expect. Let's go through an example. First, in the forward direction:
33 ///
34 /// ```rust
35 /// let mut c = 0;
36 ///
37 /// for pair in vec!['a', 'b', 'c'].into_iter()
38 ///                                .map(|letter| { c += 1; (letter, c) }) {
39 ///     println!("{:?}", pair);
40 /// }
41 /// ```
42 ///
43 /// This will print "('a', 1), ('b', 2), ('c', 3)".
44 ///
45 /// Now consider this twist where we add a call to `rev`. This version will
46 /// print `('c', 1), ('b', 2), ('a', 3)`. Note that the letters are reversed,
47 /// but the values of the counter still go in order. This is because `map()` is
48 /// still being called lazily on each item, but we are popping items off the
49 /// back of the vector now, instead of shifting them from the front.
50 ///
51 /// ```rust
52 /// let mut c = 0;
53 ///
54 /// for pair in vec!['a', 'b', 'c'].into_iter()
55 ///                                .map(|letter| { c += 1; (letter, c) })
56 ///                                .rev() {
57 ///     println!("{:?}", pair);
58 /// }
59 /// ```
60 #[must_use = "iterators are lazy and do nothing unless consumed"]
61 #[stable(feature = "rust1", since = "1.0.0")]
62 #[derive(Clone)]
63 pub struct Map<I, F> {
64     iter: I,
65     f: F,
66 }
67 impl<I, F> Map<I, F> {
68     pub(in crate::iter) fn new(iter: I, f: F) -> Map<I, F> {
69         Map { iter, f }
70     }
71 }
72
73 #[stable(feature = "core_impl_debug", since = "1.9.0")]
74 impl<I: fmt::Debug, F> fmt::Debug for Map<I, F> {
75     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76         f.debug_struct("Map").field("iter", &self.iter).finish()
77     }
78 }
79
80 fn map_fold<T, B, Acc>(
81     mut f: impl FnMut(T) -> B,
82     mut g: impl FnMut(Acc, B) -> Acc,
83 ) -> impl FnMut(Acc, T) -> Acc {
84     move |acc, elt| g(acc, f(elt))
85 }
86
87 fn map_try_fold<'a, T, B, Acc, R>(
88     f: &'a mut impl FnMut(T) -> B,
89     mut g: impl FnMut(Acc, B) -> R + 'a,
90 ) -> impl FnMut(Acc, T) -> R + 'a {
91     move |acc, elt| g(acc, f(elt))
92 }
93
94 #[stable(feature = "rust1", since = "1.0.0")]
95 impl<B, I: Iterator, F> Iterator for Map<I, F>
96 where
97     F: FnMut(I::Item) -> B,
98 {
99     type Item = B;
100
101     #[inline]
102     fn next(&mut self) -> Option<B> {
103         self.iter.next().map(&mut self.f)
104     }
105
106     #[inline]
107     fn size_hint(&self) -> (usize, Option<usize>) {
108         self.iter.size_hint()
109     }
110
111     fn try_fold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
112     where
113         Self: Sized,
114         G: FnMut(Acc, Self::Item) -> R,
115         R: Try<Ok = Acc>,
116     {
117         self.iter.try_fold(init, map_try_fold(&mut self.f, g))
118     }
119
120     fn fold<Acc, G>(self, init: Acc, g: G) -> Acc
121     where
122         G: FnMut(Acc, Self::Item) -> Acc,
123     {
124         self.iter.fold(init, map_fold(self.f, g))
125     }
126
127     unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> B
128     where
129         Self: TrustedRandomAccess,
130     {
131         // SAFETY: the caller must uphold the contract for
132         // `Iterator::__iterator_get_unchecked`.
133         unsafe { (self.f)(try_get_unchecked(&mut self.iter, idx)) }
134     }
135 }
136
137 #[stable(feature = "rust1", since = "1.0.0")]
138 impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F>
139 where
140     F: FnMut(I::Item) -> B,
141 {
142     #[inline]
143     fn next_back(&mut self) -> Option<B> {
144         self.iter.next_back().map(&mut self.f)
145     }
146
147     fn try_rfold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
148     where
149         Self: Sized,
150         G: FnMut(Acc, Self::Item) -> R,
151         R: Try<Ok = Acc>,
152     {
153         self.iter.try_rfold(init, map_try_fold(&mut self.f, g))
154     }
155
156     fn rfold<Acc, G>(self, init: Acc, g: G) -> Acc
157     where
158         G: FnMut(Acc, Self::Item) -> Acc,
159     {
160         self.iter.rfold(init, map_fold(self.f, g))
161     }
162 }
163
164 #[stable(feature = "rust1", since = "1.0.0")]
165 impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F>
166 where
167     F: FnMut(I::Item) -> B,
168 {
169     fn len(&self) -> usize {
170         self.iter.len()
171     }
172
173     fn is_empty(&self) -> bool {
174         self.iter.is_empty()
175     }
176 }
177
178 #[stable(feature = "fused", since = "1.26.0")]
179 impl<B, I: FusedIterator, F> FusedIterator for Map<I, F> where F: FnMut(I::Item) -> B {}
180
181 #[unstable(feature = "trusted_len", issue = "37572")]
182 unsafe impl<B, I, F> TrustedLen for Map<I, F>
183 where
184     I: TrustedLen,
185     F: FnMut(I::Item) -> B,
186 {
187 }
188
189 #[doc(hidden)]
190 #[unstable(feature = "trusted_random_access", issue = "none")]
191 unsafe impl<I, F> TrustedRandomAccess for Map<I, F>
192 where
193     I: TrustedRandomAccess,
194 {
195     #[inline]
196     fn may_have_side_effect() -> bool {
197         true
198     }
199 }
200
201 #[unstable(issue = "none", feature = "inplace_iteration")]
202 unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for Map<I, F>
203 where
204     F: FnMut(I::Item) -> B,
205     I: SourceIter<Source = S>,
206 {
207     type Source = S;
208
209     #[inline]
210     unsafe fn as_inner(&mut self) -> &mut S {
211         // SAFETY: unsafe function forwarding to unsafe function with the same requirements
212         unsafe { SourceIter::as_inner(&mut self.iter) }
213     }
214 }
215
216 #[unstable(issue = "none", feature = "inplace_iteration")]
217 unsafe impl<B, I: InPlaceIterable, F> InPlaceIterable for Map<I, F> where F: FnMut(I::Item) -> B {}