1use crate::cmp;
2use crate::iter::adapters::SourceIter;
3use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen, TrustedRandomAccess};
4use crate::num::NonZero;
5use crate::ops::{ControlFlow, Try};
6
7#[derive(Clone, Debug)]
15#[must_use = "iterators are lazy and do nothing unless consumed"]
16#[stable(feature = "rust1", since = "1.0.0")]
17#[ferrocene::prevalidated]
18pub struct Take<I> {
19 iter: I,
20 n: usize,
21}
22
23impl<I> Take<I> {
24 #[ferrocene::prevalidated]
25 pub(in crate::iter) fn new(iter: I, n: usize) -> Take<I> {
26 Take { iter, n }
27 }
28}
29
30#[stable(feature = "rust1", since = "1.0.0")]
31impl<I> Iterator for Take<I>
32where
33 I: Iterator,
34{
35 type Item = <I as Iterator>::Item;
36
37 #[inline]
38 #[ferrocene::prevalidated]
39 fn next(&mut self) -> Option<<I as Iterator>::Item> {
40 if self.n != 0 {
41 self.n -= 1;
42 self.iter.next()
43 } else {
44 None
45 }
46 }
47
48 #[inline]
49 #[ferrocene::prevalidated]
50 fn nth(&mut self, n: usize) -> Option<I::Item> {
51 if self.n > n {
52 self.n -= n + 1;
53 self.iter.nth(n)
54 } else {
55 if self.n > 0 {
56 self.iter.nth(self.n - 1);
57 self.n = 0;
58 }
59 None
60 }
61 }
62
63 #[inline]
64 #[ferrocene::prevalidated]
65 fn size_hint(&self) -> (usize, Option<usize>) {
66 if self.n == 0 {
67 return (0, Some(0));
68 }
69
70 let (lower, upper) = self.iter.size_hint();
71
72 let lower = cmp::min(lower, self.n);
73
74 let upper = match upper {
75 Some(x) if x < self.n => Some(x),
76 _ => Some(self.n),
77 };
78
79 (lower, upper)
80 }
81
82 #[inline]
83 #[ferrocene::prevalidated]
84 fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
85 where
86 Fold: FnMut(Acc, Self::Item) -> R,
87 R: Try<Output = Acc>,
88 {
89 #[ferrocene::prevalidated]
90 fn check<'a, T, Acc, R: Try<Output = Acc>>(
91 n: &'a mut usize,
92 mut fold: impl FnMut(Acc, T) -> R + 'a,
93 ) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> + 'a {
94 move |acc, x| {
95 *n -= 1;
96 let r = fold(acc, x);
97 if *n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) }
98 }
99 }
100
101 if self.n == 0 {
102 try { init }
103 } else {
104 let n = &mut self.n;
105 self.iter.try_fold(init, check(n, fold)).into_try()
106 }
107 }
108
109 #[inline]
110 #[ferrocene::prevalidated]
111 fn fold<B, F>(self, init: B, f: F) -> B
112 where
113 Self: Sized,
114 F: FnMut(B, Self::Item) -> B,
115 {
116 Self::spec_fold(self, init, f)
117 }
118
119 #[inline]
120 #[ferrocene::prevalidated]
121 fn for_each<F: FnMut(Self::Item)>(self, f: F) {
122 Self::spec_for_each(self, f)
123 }
124
125 #[inline]
126 #[rustc_inherit_overflow_checks]
127 #[ferrocene::prevalidated]
128 fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
129 let min = self.n.min(n);
130 let rem = match self.iter.advance_by(min) {
131 Ok(()) => 0,
132 Err(rem) => rem.get(),
133 };
134 let advanced = min - rem;
135 self.n -= advanced;
136 NonZero::new(n - advanced).map_or(Ok(()), Err)
137 }
138}
139
140#[unstable(issue = "none", feature = "inplace_iteration")]
141unsafe impl<I> SourceIter for Take<I>
142where
143 I: SourceIter,
144{
145 type Source = I::Source;
146
147 #[inline]
148 unsafe fn as_inner(&mut self) -> &mut I::Source {
149 unsafe { SourceIter::as_inner(&mut self.iter) }
151 }
152}
153
154#[unstable(issue = "none", feature = "inplace_iteration")]
155unsafe impl<I: InPlaceIterable> InPlaceIterable for Take<I> {
156 const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
157 const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
158}
159
160#[stable(feature = "double_ended_take_iterator", since = "1.38.0")]
161impl<I> DoubleEndedIterator for Take<I>
162where
163 I: DoubleEndedIterator + ExactSizeIterator,
164{
165 #[inline]
166 fn next_back(&mut self) -> Option<Self::Item> {
167 if self.n == 0 {
168 None
169 } else {
170 let n = self.n;
171 self.n -= 1;
172 self.iter.nth_back(self.iter.len().saturating_sub(n))
173 }
174 }
175
176 #[inline]
177 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
178 let len = self.iter.len();
179 if self.n > n {
180 let m = len.saturating_sub(self.n) + n;
181 self.n -= n + 1;
182 self.iter.nth_back(m)
183 } else {
184 if len > 0 {
185 self.iter.nth_back(len - 1);
186 }
187 None
188 }
189 }
190
191 #[inline]
192 fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
193 where
194 Self: Sized,
195 Fold: FnMut(Acc, Self::Item) -> R,
196 R: Try<Output = Acc>,
197 {
198 if self.n == 0 {
199 try { init }
200 } else {
201 let len = self.iter.len();
202 if len > self.n && self.iter.nth_back(len - self.n - 1).is_none() {
203 try { init }
204 } else {
205 self.iter.try_rfold(init, fold)
206 }
207 }
208 }
209
210 #[inline]
211 fn rfold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
212 where
213 Self: Sized,
214 Fold: FnMut(Acc, Self::Item) -> Acc,
215 {
216 if self.n == 0 {
217 init
218 } else {
219 let len = self.iter.len();
220 if len > self.n && self.iter.nth_back(len - self.n - 1).is_none() {
221 init
222 } else {
223 self.iter.rfold(init, fold)
224 }
225 }
226 }
227
228 #[inline]
229 #[rustc_inherit_overflow_checks]
230 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
231 let trim_inner = self.iter.len().saturating_sub(self.n);
234 let advance_by = trim_inner.saturating_add(n);
238
239 let remainder = match self.iter.advance_back_by(advance_by) {
240 Ok(()) => 0,
241 Err(rem) => rem.get(),
242 };
243 let advanced_by_inner = advance_by - remainder;
244 let advanced_by = advanced_by_inner - trim_inner;
245 self.n -= advanced_by;
246 NonZero::new(n - advanced_by).map_or(Ok(()), Err)
247 }
248}
249
250#[stable(feature = "rust1", since = "1.0.0")]
251impl<I> ExactSizeIterator for Take<I> where I: ExactSizeIterator {}
252
253#[stable(feature = "fused", since = "1.26.0")]
254impl<I> FusedIterator for Take<I> where I: FusedIterator {}
255
256#[unstable(issue = "none", feature = "trusted_fused")]
257unsafe impl<I: TrustedFused> TrustedFused for Take<I> {}
258
259#[unstable(feature = "trusted_len", issue = "37572")]
260unsafe impl<I: TrustedLen> TrustedLen for Take<I> {}
261
262trait SpecTake: Iterator {
263 fn spec_fold<B, F>(self, init: B, f: F) -> B
264 where
265 Self: Sized,
266 F: FnMut(B, Self::Item) -> B;
267
268 fn spec_for_each<F: FnMut(Self::Item)>(self, f: F);
269}
270
271impl<I: Iterator> SpecTake for Take<I> {
272 #[inline]
273 #[ferrocene::prevalidated]
274 default fn spec_fold<B, F>(mut self, init: B, f: F) -> B
275 where
276 Self: Sized,
277 F: FnMut(B, Self::Item) -> B,
278 {
279 use crate::ops::NeverShortCircuit;
280 self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
281 }
282
283 #[inline]
284 #[ferrocene::prevalidated]
285 default fn spec_for_each<F: FnMut(Self::Item)>(mut self, f: F) {
286 #[ferrocene::prevalidated]
290 fn check<'a, Item>(
291 mut action: impl FnMut(Item) + 'a,
292 ) -> impl FnMut(usize, Item) -> Option<usize> + 'a {
293 move |more, x| {
294 action(x);
295 more.checked_sub(1)
296 }
297 }
298
299 let remaining = self.n;
300 if remaining > 0 {
301 self.iter.try_fold(remaining - 1, check(f));
302 }
303 }
304}
305
306impl<I: Iterator + TrustedRandomAccess> SpecTake for Take<I> {
307 #[inline]
308 fn spec_fold<B, F>(mut self, init: B, mut f: F) -> B
309 where
310 Self: Sized,
311 F: FnMut(B, Self::Item) -> B,
312 {
313 let mut acc = init;
314 let end = self.n.min(self.iter.size());
315 for i in 0..end {
316 let val = unsafe { self.iter.__iterator_get_unchecked(i) };
318 acc = f(acc, val);
319 }
320 acc
321 }
322
323 #[inline]
324 fn spec_for_each<F: FnMut(Self::Item)>(mut self, mut f: F) {
325 let end = self.n.min(self.iter.size());
326 for i in 0..end {
327 let val = unsafe { self.iter.__iterator_get_unchecked(i) };
329 f(val);
330 }
331 }
332}
333
334#[stable(feature = "exact_size_take_repeat", since = "1.82.0")]
335impl<T: Clone> DoubleEndedIterator for Take<crate::iter::Repeat<T>> {
336 #[inline]
337 fn next_back(&mut self) -> Option<Self::Item> {
338 self.next()
339 }
340
341 #[inline]
342 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
343 self.nth(n)
344 }
345
346 #[inline]
347 fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
348 where
349 Self: Sized,
350 Fold: FnMut(Acc, Self::Item) -> R,
351 R: Try<Output = Acc>,
352 {
353 self.try_fold(init, fold)
354 }
355
356 #[inline]
357 fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
358 where
359 Self: Sized,
360 Fold: FnMut(Acc, Self::Item) -> Acc,
361 {
362 self.fold(init, fold)
363 }
364
365 #[inline]
366 #[rustc_inherit_overflow_checks]
367 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
368 self.advance_by(n)
369 }
370}
371
372#[stable(feature = "exact_size_take_repeat", since = "1.82.0")]
378impl<T: Clone> ExactSizeIterator for Take<crate::iter::Repeat<T>> {
379 fn len(&self) -> usize {
380 self.n
381 }
382}
383
384#[stable(feature = "exact_size_take_repeat", since = "1.82.0")]
385impl<F: FnMut() -> A, A> ExactSizeIterator for Take<crate::iter::RepeatWith<F>> {
386 fn len(&self) -> usize {
387 self.n
388 }
389}