Skip to main content

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