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