use crate::fmt; use crate::iter::adapters::{ zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce, }; use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; use crate::ops::Try; /// An iterator that maps the values of `iter` with `f`. /// /// This `struct` is created by the [`map`] method on [`Iterator`]. See its /// documentation for more. /// /// [`map`]: Iterator::map /// [`Iterator`]: trait.Iterator.html /// /// # Notes about side effects /// /// The [`map`] iterator implements [`DoubleEndedIterator`], meaning that /// you can also [`map`] backwards: /// /// ```rust /// let v: Vec = [1, 2, 3].into_iter().map(|x| x + 1).rev().collect(); /// /// assert_eq!(v, [4, 3, 2]); /// ``` /// /// [`DoubleEndedIterator`]: trait.DoubleEndedIterator.html /// /// But if your closure has state, iterating backwards may act in a way you do /// not expect. Let's go through an example. First, in the forward direction: /// /// ```rust /// let mut c = 0; /// /// for pair in ['a', 'b', 'c'].into_iter() /// .map(|letter| { c += 1; (letter, c) }) { /// println!("{pair:?}"); /// } /// ``` /// /// This will print `('a', 1), ('b', 2), ('c', 3)`. /// /// Now consider this twist where we add a call to `rev`. This version will /// print `('c', 1), ('b', 2), ('a', 3)`. Note that the letters are reversed, /// but the values of the counter still go in order. This is because `map()` is /// still being called lazily on each item, but we are popping items off the /// back of the vector now, instead of shifting them from the front. /// /// ```rust /// let mut c = 0; /// /// for pair in ['a', 'b', 'c'].into_iter() /// .map(|letter| { c += 1; (letter, c) }) /// .rev() { /// println!("{pair:?}"); /// } /// ``` #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] pub struct Map { // Used for `SplitWhitespace` and `SplitAsciiWhitespace` `as_str` methods pub(crate) iter: I, f: F, } impl Map { pub(in crate::iter) fn new(iter: I, f: F) -> Map { Map { iter, f } } } #[stable(feature = "core_impl_debug", since = "1.9.0")] impl fmt::Debug for Map { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Map").field("iter", &self.iter).finish() } } fn map_fold( mut f: impl FnMut(T) -> B, mut g: impl FnMut(Acc, B) -> Acc, ) -> impl FnMut(Acc, T) -> Acc { move |acc, elt| g(acc, f(elt)) } fn map_try_fold<'a, T, B, Acc, R>( f: &'a mut impl FnMut(T) -> B, mut g: impl FnMut(Acc, B) -> R + 'a, ) -> impl FnMut(Acc, T) -> R + 'a { move |acc, elt| g(acc, f(elt)) } #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Map where F: FnMut(I::Item) -> B, { type Item = B; #[inline] fn next(&mut self) -> Option { self.iter.next().map(&mut self.f) } #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } fn try_fold(&mut self, init: Acc, g: G) -> R where Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try, { self.iter.try_fold(init, map_try_fold(&mut self.f, g)) } fn fold(self, init: Acc, g: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc, { self.iter.fold(init, map_fold(self.f, g)) } #[inline] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> B where Self: TrustedRandomAccessNoCoerce, { // SAFETY: the caller must uphold the contract for // `Iterator::__iterator_get_unchecked`. unsafe { (self.f)(try_get_unchecked(&mut self.iter, idx)) } } } #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for Map where F: FnMut(I::Item) -> B, { #[inline] fn next_back(&mut self) -> Option { self.iter.next_back().map(&mut self.f) } fn try_rfold(&mut self, init: Acc, g: G) -> R where Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try, { self.iter.try_rfold(init, map_try_fold(&mut self.f, g)) } fn rfold(self, init: Acc, g: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc, { self.iter.rfold(init, map_fold(self.f, g)) } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Map where F: FnMut(I::Item) -> B, { fn len(&self) -> usize { self.iter.len() } fn is_empty(&self) -> bool { self.iter.is_empty() } } #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Map where F: FnMut(I::Item) -> B {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Map where I: TrustedLen, F: FnMut(I::Item) -> B, { } #[doc(hidden)] #[unstable(feature = "trusted_random_access", issue = "none")] unsafe impl TrustedRandomAccess for Map where I: TrustedRandomAccess {} #[doc(hidden)] #[unstable(feature = "trusted_random_access", issue = "none")] unsafe impl TrustedRandomAccessNoCoerce for Map where I: TrustedRandomAccessNoCoerce, { const MAY_HAVE_SIDE_EFFECT: bool = true; } #[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl SourceIter for Map where I: SourceIter, { type Source = I::Source; #[inline] unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } } #[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl InPlaceIterable for Map where F: FnMut(I::Item) -> B {}