1use crate::fmt;
2#[cfg(not(feature = "ferrocene_subset"))]
3use crate::iter::adapters::zip::try_get_unchecked;
4#[cfg(not(feature = "ferrocene_subset"))]
5use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
6#[cfg(not(feature = "ferrocene_subset"))]
7use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen, UncheckedIterator};
8#[cfg(not(feature = "ferrocene_subset"))]
9use crate::num::NonZero;
10use crate::ops::Try;
11
12#[cfg(feature = "ferrocene_subset")]
14#[rustfmt::skip]
15use crate::iter::{TrustedLen, UncheckedIterator};
16
17#[must_use = "iterators are lazy and do nothing unless consumed"]
68#[stable(feature = "rust1", since = "1.0.0")]
69#[derive(Clone)]
70pub struct Map<I, F> {
71 pub(crate) iter: I,
73 f: F,
74}
75
76impl<I, F> Map<I, F> {
77 pub(in crate::iter) fn new(iter: I, f: F) -> Map<I, F> {
78 Map { iter, f }
79 }
80
81 pub(crate) fn into_inner(self) -> I {
82 self.iter
83 }
84}
85
86#[stable(feature = "core_impl_debug", since = "1.9.0")]
87impl<I: fmt::Debug, F> fmt::Debug for Map<I, F> {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 f.debug_struct("Map").field("iter", &self.iter).finish()
90 }
91}
92
93fn map_fold<T, B, Acc>(
94 mut f: impl FnMut(T) -> B,
95 mut g: impl FnMut(Acc, B) -> Acc,
96) -> impl FnMut(Acc, T) -> Acc {
97 move |acc, elt| g(acc, f(elt))
98}
99
100fn map_try_fold<'a, T, B, Acc, R>(
101 f: &'a mut impl FnMut(T) -> B,
102 mut g: impl FnMut(Acc, B) -> R + 'a,
103) -> impl FnMut(Acc, T) -> R + 'a {
104 move |acc, elt| g(acc, f(elt))
105}
106
107#[stable(feature = "rust1", since = "1.0.0")]
108impl<B, I: Iterator, F> Iterator for Map<I, F>
109where
110 F: FnMut(I::Item) -> B,
111{
112 type Item = B;
113
114 #[inline]
115 fn next(&mut self) -> Option<B> {
116 self.iter.next().map(&mut self.f)
117 }
118
119 #[inline]
120 fn size_hint(&self) -> (usize, Option<usize>) {
121 self.iter.size_hint()
122 }
123
124 fn try_fold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
125 where
126 Self: Sized,
127 G: FnMut(Acc, Self::Item) -> R,
128 R: Try<Output = Acc>,
129 {
130 self.iter.try_fold(init, map_try_fold(&mut self.f, g))
131 }
132
133 fn fold<Acc, G>(self, init: Acc, g: G) -> Acc
134 where
135 G: FnMut(Acc, Self::Item) -> Acc,
136 {
137 self.iter.fold(init, map_fold(self.f, g))
138 }
139
140 #[inline]
141 #[cfg(not(feature = "ferrocene_subset"))]
142 unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> B
143 where
144 Self: TrustedRandomAccessNoCoerce,
145 {
146 unsafe { (self.f)(try_get_unchecked(&mut self.iter, idx)) }
149 }
150}
151
152#[stable(feature = "rust1", since = "1.0.0")]
153impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F>
154where
155 F: FnMut(I::Item) -> B,
156{
157 #[inline]
158 fn next_back(&mut self) -> Option<B> {
159 self.iter.next_back().map(&mut self.f)
160 }
161
162 fn try_rfold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
163 where
164 Self: Sized,
165 G: FnMut(Acc, Self::Item) -> R,
166 R: Try<Output = Acc>,
167 {
168 self.iter.try_rfold(init, map_try_fold(&mut self.f, g))
169 }
170
171 fn rfold<Acc, G>(self, init: Acc, g: G) -> Acc
172 where
173 G: FnMut(Acc, Self::Item) -> Acc,
174 {
175 self.iter.rfold(init, map_fold(self.f, g))
176 }
177}
178
179#[stable(feature = "rust1", since = "1.0.0")]
180#[cfg(not(feature = "ferrocene_subset"))]
181impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F>
182where
183 F: FnMut(I::Item) -> B,
184{
185 fn len(&self) -> usize {
186 self.iter.len()
187 }
188
189 fn is_empty(&self) -> bool {
190 self.iter.is_empty()
191 }
192}
193
194#[stable(feature = "fused", since = "1.26.0")]
195#[cfg(not(feature = "ferrocene_subset"))]
196impl<B, I: FusedIterator, F> FusedIterator for Map<I, F> where F: FnMut(I::Item) -> B {}
197
198#[unstable(issue = "none", feature = "trusted_fused")]
199#[cfg(not(feature = "ferrocene_subset"))]
200unsafe impl<I: TrustedFused, F> TrustedFused for Map<I, F> {}
201
202#[unstable(feature = "trusted_len", issue = "37572")]
203unsafe impl<B, I, F> TrustedLen for Map<I, F>
204where
205 I: TrustedLen,
206 F: FnMut(I::Item) -> B,
207{
208}
209
210impl<B, I, F> UncheckedIterator for Map<I, F>
211where
212 I: UncheckedIterator,
213 F: FnMut(I::Item) -> B,
214{
215 unsafe fn next_unchecked(&mut self) -> B {
216 let item = unsafe { self.iter.next_unchecked() };
219 (self.f)(item)
220 }
221}
222
223#[doc(hidden)]
224#[unstable(feature = "trusted_random_access", issue = "none")]
225#[cfg(not(feature = "ferrocene_subset"))]
226unsafe impl<I, F> TrustedRandomAccess for Map<I, F> where I: TrustedRandomAccess {}
227
228#[doc(hidden)]
229#[unstable(feature = "trusted_random_access", issue = "none")]
230#[cfg(not(feature = "ferrocene_subset"))]
231unsafe impl<I, F> TrustedRandomAccessNoCoerce for Map<I, F>
232where
233 I: TrustedRandomAccessNoCoerce,
234{
235 const MAY_HAVE_SIDE_EFFECT: bool = true;
236}
237
238#[unstable(issue = "none", feature = "inplace_iteration")]
239#[cfg(not(feature = "ferrocene_subset"))]
240unsafe impl<I, F> SourceIter for Map<I, F>
241where
242 I: SourceIter,
243{
244 type Source = I::Source;
245
246 #[inline]
247 unsafe fn as_inner(&mut self) -> &mut I::Source {
248 unsafe { SourceIter::as_inner(&mut self.iter) }
250 }
251}
252
253#[unstable(issue = "none", feature = "inplace_iteration")]
254#[cfg(not(feature = "ferrocene_subset"))]
255unsafe impl<I: InPlaceIterable, F> InPlaceIterable for Map<I, F> {
256 const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
257 const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
258}