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