]> git.proxmox.com Git - rustc.git/blame - library/core/src/iter/adapters/enumerate.rs
New upstream version 1.55.0+dfsg1
[rustc.git] / library / core / src / iter / adapters / enumerate.rs
CommitLineData
fc512014
XL
1use crate::iter::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess};
2use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
6a06907d 3use crate::ops::Try;
fc512014
XL
4
5/// An iterator that yields the current count and the element during iteration.
6///
7/// This `struct` is created by the [`enumerate`] method on [`Iterator`]. See its
8/// documentation for more.
9///
10/// [`enumerate`]: Iterator::enumerate
11/// [`Iterator`]: trait.Iterator.html
12#[derive(Clone, Debug)]
13#[must_use = "iterators are lazy and do nothing unless consumed"]
14#[stable(feature = "rust1", since = "1.0.0")]
15pub struct Enumerate<I> {
16 iter: I,
17 count: usize,
18}
19impl<I> Enumerate<I> {
20 pub(in crate::iter) fn new(iter: I) -> Enumerate<I> {
21 Enumerate { iter, count: 0 }
22 }
23}
24
25#[stable(feature = "rust1", since = "1.0.0")]
26impl<I> Iterator for Enumerate<I>
27where
28 I: Iterator,
29{
30 type Item = (usize, <I as Iterator>::Item);
31
32 /// # Overflow Behavior
33 ///
34 /// The method does no guarding against overflows, so enumerating more than
35 /// `usize::MAX` elements either produces the wrong result or panics. If
36 /// debug assertions are enabled, a panic is guaranteed.
37 ///
38 /// # Panics
39 ///
40 /// Might panic if the index of the element overflows a `usize`.
41 #[inline]
6a06907d 42 #[rustc_inherit_overflow_checks]
fc512014
XL
43 fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
44 let a = self.iter.next()?;
45 let i = self.count;
6a06907d 46 self.count += 1;
fc512014
XL
47 Some((i, a))
48 }
49
50 #[inline]
51 fn size_hint(&self) -> (usize, Option<usize>) {
52 self.iter.size_hint()
53 }
54
55 #[inline]
6a06907d 56 #[rustc_inherit_overflow_checks]
fc512014
XL
57 fn nth(&mut self, n: usize) -> Option<(usize, I::Item)> {
58 let a = self.iter.nth(n)?;
6a06907d
XL
59 let i = self.count + n;
60 self.count = i + 1;
fc512014
XL
61 Some((i, a))
62 }
63
64 #[inline]
65 fn count(self) -> usize {
66 self.iter.count()
67 }
68
69 #[inline]
70 fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
71 where
72 Self: Sized,
73 Fold: FnMut(Acc, Self::Item) -> R,
17df50a5 74 R: Try<Output = Acc>,
fc512014
XL
75 {
76 #[inline]
77 fn enumerate<'a, T, Acc, R>(
78 count: &'a mut usize,
79 mut fold: impl FnMut(Acc, (usize, T)) -> R + 'a,
80 ) -> impl FnMut(Acc, T) -> R + 'a {
6a06907d 81 #[rustc_inherit_overflow_checks]
fc512014
XL
82 move |acc, item| {
83 let acc = fold(acc, (*count, item));
6a06907d 84 *count += 1;
fc512014
XL
85 acc
86 }
87 }
88
89 self.iter.try_fold(init, enumerate(&mut self.count, fold))
90 }
91
92 #[inline]
93 fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
94 where
95 Fold: FnMut(Acc, Self::Item) -> Acc,
96 {
97 #[inline]
98 fn enumerate<T, Acc>(
99 mut count: usize,
100 mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
101 ) -> impl FnMut(Acc, T) -> Acc {
6a06907d 102 #[rustc_inherit_overflow_checks]
fc512014
XL
103 move |acc, item| {
104 let acc = fold(acc, (count, item));
6a06907d 105 count += 1;
fc512014
XL
106 acc
107 }
108 }
109
110 self.iter.fold(init, enumerate(self.count, fold))
111 }
112
6a06907d 113 #[rustc_inherit_overflow_checks]
136023e0 114 #[doc(hidden)]
fc512014
XL
115 unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
116 where
117 Self: TrustedRandomAccess,
118 {
119 // SAFETY: the caller must uphold the contract for
120 // `Iterator::__iterator_get_unchecked`.
121 let value = unsafe { try_get_unchecked(&mut self.iter, idx) };
6a06907d 122 (self.count + idx, value)
fc512014
XL
123 }
124}
125
126#[stable(feature = "rust1", since = "1.0.0")]
127impl<I> DoubleEndedIterator for Enumerate<I>
128where
129 I: ExactSizeIterator + DoubleEndedIterator,
130{
131 #[inline]
132 fn next_back(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
133 let a = self.iter.next_back()?;
134 let len = self.iter.len();
135 // Can safely add, `ExactSizeIterator` promises that the number of
136 // elements fits into a `usize`.
137 Some((self.count + len, a))
138 }
139
140 #[inline]
141 fn nth_back(&mut self, n: usize) -> Option<(usize, <I as Iterator>::Item)> {
142 let a = self.iter.nth_back(n)?;
143 let len = self.iter.len();
144 // Can safely add, `ExactSizeIterator` promises that the number of
145 // elements fits into a `usize`.
146 Some((self.count + len, a))
147 }
148
149 #[inline]
150 fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
151 where
152 Self: Sized,
153 Fold: FnMut(Acc, Self::Item) -> R,
17df50a5 154 R: Try<Output = Acc>,
fc512014
XL
155 {
156 // Can safely add and subtract the count, as `ExactSizeIterator` promises
157 // that the number of elements fits into a `usize`.
158 fn enumerate<T, Acc, R>(
159 mut count: usize,
160 mut fold: impl FnMut(Acc, (usize, T)) -> R,
161 ) -> impl FnMut(Acc, T) -> R {
162 move |acc, item| {
163 count -= 1;
164 fold(acc, (count, item))
165 }
166 }
167
168 let count = self.count + self.iter.len();
169 self.iter.try_rfold(init, enumerate(count, fold))
170 }
171
172 #[inline]
173 fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
174 where
175 Fold: FnMut(Acc, Self::Item) -> Acc,
176 {
177 // Can safely add and subtract the count, as `ExactSizeIterator` promises
178 // that the number of elements fits into a `usize`.
179 fn enumerate<T, Acc>(
180 mut count: usize,
181 mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
182 ) -> impl FnMut(Acc, T) -> Acc {
183 move |acc, item| {
184 count -= 1;
185 fold(acc, (count, item))
186 }
187 }
188
189 let count = self.count + self.iter.len();
190 self.iter.rfold(init, enumerate(count, fold))
191 }
192}
193
194#[stable(feature = "rust1", since = "1.0.0")]
195impl<I> ExactSizeIterator for Enumerate<I>
196where
197 I: ExactSizeIterator,
198{
199 fn len(&self) -> usize {
200 self.iter.len()
201 }
202
203 fn is_empty(&self) -> bool {
204 self.iter.is_empty()
205 }
206}
207
208#[doc(hidden)]
209#[unstable(feature = "trusted_random_access", issue = "none")]
210unsafe impl<I> TrustedRandomAccess for Enumerate<I>
211where
212 I: TrustedRandomAccess,
213{
6a06907d 214 const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
fc512014
XL
215}
216
217#[stable(feature = "fused", since = "1.26.0")]
218impl<I> FusedIterator for Enumerate<I> where I: FusedIterator {}
219
220#[unstable(feature = "trusted_len", issue = "37572")]
221unsafe impl<I> TrustedLen for Enumerate<I> where I: TrustedLen {}
222
223#[unstable(issue = "none", feature = "inplace_iteration")]
224unsafe impl<S: Iterator, I: Iterator> SourceIter for Enumerate<I>
225where
226 I: SourceIter<Source = S>,
227{
228 type Source = S;
229
230 #[inline]
231 unsafe fn as_inner(&mut self) -> &mut S {
232 // SAFETY: unsafe function forwarding to unsafe function with the same requirements
233 unsafe { SourceIter::as_inner(&mut self.iter) }
234 }
235}
236
237#[unstable(issue = "none", feature = "inplace_iteration")]
238unsafe impl<I: InPlaceIterable> InPlaceIterable for Enumerate<I> {}