]> git.proxmox.com Git - rustc.git/blob - library/core/src/iter/adapters/enumerate.rs
New upstream version 1.57.0+dfsg1
[rustc.git] / library / core / src / iter / adapters / enumerate.rs
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> {
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]
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]
53 fn size_hint(&self) -> (usize, Option<usize>) {
54 self.iter.size_hint()
55 }
56
57 #[inline]
58 #[rustc_inherit_overflow_checks]
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]
67 fn count(self) -> usize {
68 self.iter.count()
69 }
70
71 #[inline]
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]
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]
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)]
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]
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]
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]
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]
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]
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 {
223 fn len(&self) -> usize {
224 self.iter.len()
225 }
226
227 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]
259 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> {}