]>
Commit | Line | Data |
---|---|---|
fc512014 XL |
1 | use crate::iter::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess}; |
2 | use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; | |
6a06907d | 3 | use 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")] | |
15 | pub struct Enumerate<I> { | |
16 | iter: I, | |
17 | count: usize, | |
18 | } | |
19 | impl<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")] | |
26 | impl<I> Iterator for Enumerate<I> | |
27 | where | |
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")] | |
127 | impl<I> DoubleEndedIterator for Enumerate<I> | |
128 | where | |
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")] | |
195 | impl<I> ExactSizeIterator for Enumerate<I> | |
196 | where | |
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")] | |
210 | unsafe impl<I> TrustedRandomAccess for Enumerate<I> | |
211 | where | |
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")] | |
218 | impl<I> FusedIterator for Enumerate<I> where I: FusedIterator {} | |
219 | ||
220 | #[unstable(feature = "trusted_len", issue = "37572")] | |
221 | unsafe impl<I> TrustedLen for Enumerate<I> where I: TrustedLen {} | |
222 | ||
223 | #[unstable(issue = "none", feature = "inplace_iteration")] | |
224 | unsafe impl<S: Iterator, I: Iterator> SourceIter for Enumerate<I> | |
225 | where | |
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")] | |
238 | unsafe impl<I: InPlaceIterable> InPlaceIterable for Enumerate<I> {} |