core/iter/adapters/
map.rs

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

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy