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