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(iter:Default::default())
316 }
317}
318