enumerate.rs - source
Description: Source of the Rust file `library/core/src/iter/adapters/enumerate.rs`.

#
core/iter/adapters/
enumerate.rs

    1use crate::iter::adapters::zip::try_get_unchecked;
    2use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
    3use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen};
    4use crate::num::NonZero;
    5use crate::ops::Try;
    6
    7/// An iterator that yields the current count and the element during iteration.
    8///
    9/// This `struct` is created by the [`enumerate`] method on [`Iterator`]. See its
    10/// documentation for more.
    11///
    12/// [`enumerate`]: Iterator::enumerate
    13/// [`Iterator`]: trait.Iterator.html
    14#[derive(Clone, Debug)]
    15#[must_use = "iterators are lazy and do nothing unless consumed"]
    16#[stable(feature = "rust1", since = "1.0.0")]
    17#[rustc_diagnostic_item = "Enumerate"]
    18pub struct Enumerate<I> {
    19    iter: I,
    20    count: usize,
    21}
    22impl<I> Enumerate<I> {
    23    pub(in crate::iter) fn new(iter: I) -> Enumerate<I> {
    24        Enumerate { iter, count: 0 }
    25    }
    26
    27    /// Retrieve the current position of the iterator.
    28    ///
    29    /// If the iterator has not advanced, the position returned will be 0.
    30    ///
    31    /// The position may also exceed the bounds of the iterator to allow for calculating
    32    /// the displacement of the iterator from following calls to [`Iterator::next`].
    33    ///
    34    /// # Examples
    35    ///
    36    /// ```
    37    /// #![feature(next_index)]
    38    ///
    39    /// let arr = ['a', 'b'];
    40    ///
    41    /// let mut iter = arr.iter().enumerate();
    42    ///
    43    /// assert_eq!(iter.next_index(), 0);
    44    /// assert_eq!(iter.next(), Some((0, &'a')));
    45    ///
    46    /// assert_eq!(iter.next_index(), 1);
    47    /// assert_eq!(iter.next_index(), 1);
    48    /// assert_eq!(iter.next(), Some((1, &'b')));
    49    ///
    50    /// assert_eq!(iter.next_index(), 2);
    51    /// assert_eq!(iter.next(), None);
    52    /// assert_eq!(iter.next_index(), 2);
    53    /// ```
    54    #[inline]
    55    #[unstable(feature = "next_index", issue = "130711")]
    56    pub fn next_index(&self) -> usize {
    57        self.count
    58    }
    59}
    60
    61#[stable(feature = "rust1", since = "1.0.0")]
    62impl<I> Iterator for Enumerate<I>
    63where
    64    I: Iterator,
    65{
    66    type Item = (usize, <I as Iterator>::Item);
    67
    68    /// # Overflow Behavior
    69    ///
    70    /// The method does no guarding against overflows, so enumerating more than
    71    /// `usize::MAX` elements either produces the wrong result or panics. If
    72    /// overflow checks are enabled, a panic is guaranteed.
    73    ///
    74    /// # Panics
    75    ///
    76    /// Might panic if the index of the element overflows a `usize`.
    77    #[inline]
    78    #[rustc_inherit_overflow_checks]
    79    fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
    80        let a = self.iter.next()?;
    81        let i = self.count;
    82        self.count += 1;
    83        Some((i, a))
    84    }
    85
    86    #[inline]
    87    fn size_hint(&self) -> (usize, Option<usize>) {
    88        self.iter.size_hint()
    89    }
    90
    91    #[inline]
    92    #[rustc_inherit_overflow_checks]
    93    fn nth(&mut self, n: usize) -> Option<(usize, I::Item)> {
    94        let a = self.iter.nth(n)?;
    95        let i = self.count + n;
    96        self.count = i + 1;
    97        Some((i, a))
    98    }
    99
    100    #[inline]
    101    fn count(self) -> usize {
    102        self.iter.count()
    103    }
    104
    105    #[inline]
    106    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    107    where
    108        Self: Sized,
    109        Fold: FnMut(Acc, Self::Item) -> R,
    110        R: Try<Output = Acc>,
    111    {
    112        #[inline]
    113        fn enumerate<'a, T, Acc, R>(
    114            count: &'a mut usize,
    115            mut fold: impl FnMut(Acc, (usize, T)) -> R + 'a,
    116        ) -> impl FnMut(Acc, T) -> R + 'a {
    117            #[rustc_inherit_overflow_checks]
    118            move |acc, item| {
    119                let acc = fold(acc, (*count, item));
    120                *count += 1;
    121                acc
    122            }
    123        }
    124
    125        self.iter.try_fold(init, enumerate(&mut self.count, fold))
    126    }
    127
    128    #[inline]
    129    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    130    where
    131        Fold: FnMut(Acc, Self::Item) -> Acc,
    132    {
    133        #[inline]
    134        fn enumerate<T, Acc>(
    135            mut count: usize,
    136            mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
    137        ) -> impl FnMut(Acc, T) -> Acc {
    138            #[rustc_inherit_overflow_checks]
    139            move |acc, item| {
    140                let acc = fold(acc, (count, item));
    141                count += 1;
    142                acc
    143            }
    144        }
    145
    146        self.iter.fold(init, enumerate(self.count, fold))
    147    }
    148
    149    #[inline]
    150    #[rustc_inherit_overflow_checks]
    151    fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
    152        let remaining = self.iter.advance_by(n);
    153        let advanced = match remaining {
    154            Ok(()) => n,
    155            Err(rem) => n - rem.get(),
    156        };
    157        self.count += advanced;
    158        remaining
    159    }
    160
    161    #[rustc_inherit_overflow_checks]
    162    #[inline]
    163    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
    164    where
    165        Self: TrustedRandomAccessNoCoerce,
    166    {
    167        // SAFETY: the caller must uphold the contract for
    168        // `Iterator::__iterator_get_unchecked`.
    169        let value = unsafe { try_get_unchecked(&mut self.iter, idx) };
    170        (self.count + idx, value)
    171    }
    172}
    173
    174#[stable(feature = "rust1", since = "1.0.0")]
    175impl<I> DoubleEndedIterator for Enumerate<I>
    176where
    177    I: ExactSizeIterator + DoubleEndedIterator,
    178{
    179    #[inline]
    180    fn next_back(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
    181        let a = self.iter.next_back()?;
    182        let len = self.iter.len();
    183        // Can safely add, `ExactSizeIterator` promises that the number of
    184        // elements fits into a `usize`.
    185        Some((self.count + len, a))
    186    }
    187
    188    #[inline]
    189    fn nth_back(&mut self, n: usize) -> Option<(usize, <I as Iterator>::Item)> {
    190        let a = self.iter.nth_back(n)?;
    191        let len = self.iter.len();
    192        // Can safely add, `ExactSizeIterator` promises that the number of
    193        // elements fits into a `usize`.
    194        Some((self.count + len, a))
    195    }
    196
    197    #[inline]
    198    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    199    where
    200        Self: Sized,
    201        Fold: FnMut(Acc, Self::Item) -> R,
    202        R: Try<Output = Acc>,
    203    {
    204        // Can safely add and subtract the count, as `ExactSizeIterator` promises
    205        // that the number of elements fits into a `usize`.
    206        fn enumerate<T, Acc, R>(
    207            mut count: usize,
    208            mut fold: impl FnMut(Acc, (usize, T)) -> R,
    209        ) -> impl FnMut(Acc, T) -> R {
    210            move |acc, item| {
    211                count -= 1;
    212                fold(acc, (count, item))
    213            }
    214        }
    215
    216        let count = self.count + self.iter.len();
    217        self.iter.try_rfold(init, enumerate(count, fold))
    218    }
    219
    220    #[inline]
    221    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    222    where
    223        Fold: FnMut(Acc, Self::Item) -> Acc,
    224    {
    225        // Can safely add and subtract the count, as `ExactSizeIterator` promises
    226        // that the number of elements fits into a `usize`.
    227        fn enumerate<T, Acc>(
    228            mut count: usize,
    229            mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
    230        ) -> impl FnMut(Acc, T) -> Acc {
    231            move |acc, item| {
    232                count -= 1;
    233                fold(acc, (count, item))
    234            }
    235        }
    236
    237        let count = self.count + self.iter.len();
    238        self.iter.rfold(init, enumerate(count, fold))
    239    }
    240
    241    #[inline]
    242    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
    243        // we do not need to update the count since that only tallies the number of items
    244        // consumed from the front. consuming items from the back can never reduce that.
    245        self.iter.advance_back_by(n)
    246    }
    247}
    248
    249#[stable(feature = "rust1", since = "1.0.0")]
    250impl<I> ExactSizeIterator for Enumerate<I>
    251where
    252    I: ExactSizeIterator,
    253{
    254    fn len(&self) -> usize {
    255        self.iter.len()
    256    }
    257
    258    fn is_empty(&self) -> bool {
    259        self.iter.is_empty()
    260    }
    261}
    262
    263#[doc(hidden)]
    264#[unstable(feature = "trusted_random_access", issue = "none")]
    265unsafe impl<I> TrustedRandomAccess for Enumerate<I> where I: TrustedRandomAccess {}
    266
    267#[doc(hidden)]
    268#[unstable(feature = "trusted_random_access", issue = "none")]
    269unsafe impl<I> TrustedRandomAccessNoCoerce for Enumerate<I>
    270where
    271    I: TrustedRandomAccessNoCoerce,
    272{
    273    const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
    274}
    275
    276#[stable(feature = "fused", since = "1.26.0")]
    277impl<I> FusedIterator for Enumerate<I> where I: FusedIterator {}
    278
    279#[unstable(issue = "none", feature = "trusted_fused")]
    280unsafe impl<I: TrustedFused> TrustedFused for Enumerate<I> {}
    281
    282#[unstable(feature = "trusted_len", issue = "37572")]
    283unsafe impl<I> TrustedLen for Enumerate<I> where I: TrustedLen {}
    284
    285#[unstable(issue = "none", feature = "inplace_iteration")]
    286unsafe impl<I> SourceIter for Enumerate<I>
    287where
    288    I: SourceIter,
    289{
    290    type Source = I::Source;
    291
    292    #[inline]
    293    unsafe fn as_inner(&mut self) -> &mut I::Source {
    294        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
    295        unsafe { SourceIter::as_inner(&mut self.iter) }
    296    }
    297}
    298
    299#[unstable(issue = "none", feature = "inplace_iteration")]
    300unsafe impl<I: InPlaceIterable> InPlaceIterable for Enumerate<I> {
    301    const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
    302    const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
    303}
    304
    305#[stable(feature = "default_iters", since = "1.70.0")]
    306impl<I: Default> Default for Enumerate<I> {
    307    /// Creates an `Enumerate` iterator from the default value of `I`
    308    /// ```
    309    /// # use core::slice;
    310    /// # use std::iter::Enumerate;
    311    /// let iter: Enumerate<slice::Iter<'_, u8>> = Default::default();
    312    /// assert_eq!(iter.len(), 0);
    313    /// ```
    314    fn default() -> Self {
    315        Enumerate::new(Default::default())
    316    }
    317}