1#[cfg(not(feature = "ferrocene_subset"))]
2use crate::intrinsics;
3#[cfg(not(feature = "ferrocene_subset"))]
4use crate::iter::adapters::SourceIter;
5#[cfg(not(feature = "ferrocene_subset"))]
6use crate::iter::adapters::zip::try_get_unchecked;
7#[cfg(not(feature = "ferrocene_subset"))]
8use crate::iter::{
9 FusedIterator, TrustedFused, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
10};
11#[cfg(not(feature = "ferrocene_subset"))]
12use crate::ops::Try;
13
14#[derive(Clone, Debug)]
20#[must_use = "iterators are lazy and do nothing unless consumed"]
21#[stable(feature = "rust1", since = "1.0.0")]
22pub struct Fuse<I> {
23 iter: Option<I>,
27}
28impl<I> Fuse<I> {
29 pub(in crate::iter) fn new(iter: I) -> Fuse<I> {
30 Fuse { iter: Some(iter) }
31 }
32
33 pub(crate) fn into_inner(self) -> Option<I> {
34 self.iter
35 }
36}
37
38#[cfg(not(feature = "ferrocene_subset"))]
39#[stable(feature = "fused", since = "1.26.0")]
40impl<I> FusedIterator for Fuse<I> where I: Iterator {}
41
42#[cfg(not(feature = "ferrocene_subset"))]
43#[unstable(issue = "none", feature = "trusted_fused")]
44unsafe impl<I> TrustedFused for Fuse<I> where I: TrustedFused {}
45
46#[cfg(not(feature = "ferrocene_subset"))]
49#[stable(feature = "rust1", since = "1.0.0")]
50impl<I> Iterator for Fuse<I>
51where
52 I: Iterator,
53{
54 type Item = <I as Iterator>::Item;
55
56 #[inline]
57 fn next(&mut self) -> Option<Self::Item> {
58 FuseImpl::next(self)
59 }
60
61 #[inline]
62 fn nth(&mut self, n: usize) -> Option<I::Item> {
63 FuseImpl::nth(self, n)
64 }
65
66 #[inline]
67 fn last(self) -> Option<Self::Item> {
68 match self.iter {
69 Some(iter) => iter.last(),
70 None => None,
71 }
72 }
73
74 #[inline]
75 fn count(self) -> usize {
76 match self.iter {
77 Some(iter) => iter.count(),
78 None => 0,
79 }
80 }
81
82 #[inline]
83 fn size_hint(&self) -> (usize, Option<usize>) {
84 match self.iter {
85 Some(ref iter) => iter.size_hint(),
86 None => (0, Some(0)),
87 }
88 }
89
90 #[inline]
91 fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
92 where
93 Self: Sized,
94 Fold: FnMut(Acc, Self::Item) -> R,
95 R: Try<Output = Acc>,
96 {
97 FuseImpl::try_fold(self, acc, fold)
98 }
99
100 #[inline]
101 fn fold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
102 where
103 Fold: FnMut(Acc, Self::Item) -> Acc,
104 {
105 if let Some(iter) = self.iter {
106 acc = iter.fold(acc, fold);
107 }
108 acc
109 }
110
111 #[inline]
112 fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
113 where
114 P: FnMut(&Self::Item) -> bool,
115 {
116 FuseImpl::find(self, predicate)
117 }
118
119 #[inline]
120 unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
121 where
122 Self: TrustedRandomAccessNoCoerce,
123 {
124 match self.iter {
125 Some(ref mut iter) => unsafe { try_get_unchecked(iter, idx) },
128 None => unsafe { intrinsics::unreachable() },
130 }
131 }
132}
133
134#[cfg(not(feature = "ferrocene_subset"))]
135#[stable(feature = "rust1", since = "1.0.0")]
136impl<I> DoubleEndedIterator for Fuse<I>
137where
138 I: DoubleEndedIterator,
139{
140 #[inline]
141 fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
142 FuseImpl::next_back(self)
143 }
144
145 #[inline]
146 fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
147 FuseImpl::nth_back(self, n)
148 }
149
150 #[inline]
151 fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
152 where
153 Self: Sized,
154 Fold: FnMut(Acc, Self::Item) -> R,
155 R: Try<Output = Acc>,
156 {
157 FuseImpl::try_rfold(self, acc, fold)
158 }
159
160 #[inline]
161 fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
162 where
163 Fold: FnMut(Acc, Self::Item) -> Acc,
164 {
165 if let Some(iter) = self.iter {
166 acc = iter.rfold(acc, fold);
167 }
168 acc
169 }
170
171 #[inline]
172 fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
173 where
174 P: FnMut(&Self::Item) -> bool,
175 {
176 FuseImpl::rfind(self, predicate)
177 }
178}
179
180#[cfg(not(feature = "ferrocene_subset"))]
181#[stable(feature = "rust1", since = "1.0.0")]
182impl<I> ExactSizeIterator for Fuse<I>
183where
184 I: ExactSizeIterator,
185{
186 fn len(&self) -> usize {
187 match self.iter {
188 Some(ref iter) => iter.len(),
189 None => 0,
190 }
191 }
192
193 fn is_empty(&self) -> bool {
194 match self.iter {
195 Some(ref iter) => iter.is_empty(),
196 None => true,
197 }
198 }
199}
200
201#[cfg(not(feature = "ferrocene_subset"))]
202#[stable(feature = "default_iters", since = "1.70.0")]
203impl<I: Default> Default for Fuse<I> {
204 fn default() -> Self {
235 Fuse { iter: Some(I::default()) }
236 }
237}
238
239#[cfg(not(feature = "ferrocene_subset"))]
240#[unstable(feature = "trusted_len", issue = "37572")]
241unsafe impl<I> TrustedLen for Fuse<I> where I: TrustedLen {}
245
246#[cfg(not(feature = "ferrocene_subset"))]
247#[doc(hidden)]
248#[unstable(feature = "trusted_random_access", issue = "none")]
249unsafe impl<I> TrustedRandomAccess for Fuse<I> where I: TrustedRandomAccess {}
255
256#[cfg(not(feature = "ferrocene_subset"))]
257#[doc(hidden)]
258#[unstable(feature = "trusted_random_access", issue = "none")]
259unsafe impl<I> TrustedRandomAccessNoCoerce for Fuse<I>
260where
261 I: TrustedRandomAccessNoCoerce,
262{
263 const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
264}
265
266#[cfg(not(feature = "ferrocene_subset"))]
271#[doc(hidden)]
272trait FuseImpl<I> {
273 type Item;
274
275 fn next(&mut self) -> Option<Self::Item>;
277 fn nth(&mut self, n: usize) -> Option<Self::Item>;
278 fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
279 where
280 Self: Sized,
281 Fold: FnMut(Acc, Self::Item) -> R,
282 R: Try<Output = Acc>;
283 fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
284 where
285 P: FnMut(&Self::Item) -> bool;
286
287 fn next_back(&mut self) -> Option<Self::Item>
289 where
290 I: DoubleEndedIterator;
291 fn nth_back(&mut self, n: usize) -> Option<Self::Item>
292 where
293 I: DoubleEndedIterator;
294 fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
295 where
296 Self: Sized,
297 Fold: FnMut(Acc, Self::Item) -> R,
298 R: Try<Output = Acc>,
299 I: DoubleEndedIterator;
300 fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
301 where
302 P: FnMut(&Self::Item) -> bool,
303 I: DoubleEndedIterator;
304}
305
306#[cfg(not(feature = "ferrocene_subset"))]
308#[doc(hidden)]
309impl<I> FuseImpl<I> for Fuse<I>
310where
311 I: Iterator,
312{
313 type Item = <I as Iterator>::Item;
314
315 #[inline]
316 default fn next(&mut self) -> Option<<I as Iterator>::Item> {
317 and_then_or_clear(&mut self.iter, Iterator::next)
318 }
319
320 #[inline]
321 default fn nth(&mut self, n: usize) -> Option<I::Item> {
322 and_then_or_clear(&mut self.iter, |iter| iter.nth(n))
323 }
324
325 #[inline]
326 default fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
327 where
328 Self: Sized,
329 Fold: FnMut(Acc, Self::Item) -> R,
330 R: Try<Output = Acc>,
331 {
332 if let Some(ref mut iter) = self.iter {
333 acc = iter.try_fold(acc, fold)?;
334 self.iter = None;
335 }
336 try { acc }
337 }
338
339 #[inline]
340 default fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
341 where
342 P: FnMut(&Self::Item) -> bool,
343 {
344 and_then_or_clear(&mut self.iter, |iter| iter.find(predicate))
345 }
346
347 #[inline]
348 default fn next_back(&mut self) -> Option<<I as Iterator>::Item>
349 where
350 I: DoubleEndedIterator,
351 {
352 and_then_or_clear(&mut self.iter, |iter| iter.next_back())
353 }
354
355 #[inline]
356 default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
357 where
358 I: DoubleEndedIterator,
359 {
360 and_then_or_clear(&mut self.iter, |iter| iter.nth_back(n))
361 }
362
363 #[inline]
364 default fn try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
365 where
366 Self: Sized,
367 Fold: FnMut(Acc, Self::Item) -> R,
368 R: Try<Output = Acc>,
369 I: DoubleEndedIterator,
370 {
371 if let Some(ref mut iter) = self.iter {
372 acc = iter.try_rfold(acc, fold)?;
373 self.iter = None;
374 }
375 try { acc }
376 }
377
378 #[inline]
379 default fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
380 where
381 P: FnMut(&Self::Item) -> bool,
382 I: DoubleEndedIterator,
383 {
384 and_then_or_clear(&mut self.iter, |iter| iter.rfind(predicate))
385 }
386}
387
388#[cfg(not(feature = "ferrocene_subset"))]
391#[doc(hidden)]
392impl<I> FuseImpl<I> for Fuse<I>
393where
394 I: FusedIterator,
395{
396 #[inline]
397 fn next(&mut self) -> Option<<I as Iterator>::Item> {
398 self.iter.as_mut()?.next()
399 }
400
401 #[inline]
402 fn nth(&mut self, n: usize) -> Option<I::Item> {
403 self.iter.as_mut()?.nth(n)
404 }
405
406 #[inline]
407 fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
408 where
409 Self: Sized,
410 Fold: FnMut(Acc, Self::Item) -> R,
411 R: Try<Output = Acc>,
412 {
413 if let Some(ref mut iter) = self.iter {
414 acc = iter.try_fold(acc, fold)?;
415 }
416 try { acc }
417 }
418
419 #[inline]
420 fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
421 where
422 P: FnMut(&Self::Item) -> bool,
423 {
424 self.iter.as_mut()?.find(predicate)
425 }
426
427 #[inline]
428 fn next_back(&mut self) -> Option<<I as Iterator>::Item>
429 where
430 I: DoubleEndedIterator,
431 {
432 self.iter.as_mut()?.next_back()
433 }
434
435 #[inline]
436 fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
437 where
438 I: DoubleEndedIterator,
439 {
440 self.iter.as_mut()?.nth_back(n)
441 }
442
443 #[inline]
444 fn try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
445 where
446 Self: Sized,
447 Fold: FnMut(Acc, Self::Item) -> R,
448 R: Try<Output = Acc>,
449 I: DoubleEndedIterator,
450 {
451 if let Some(ref mut iter) = self.iter {
452 acc = iter.try_rfold(acc, fold)?;
453 }
454 try { acc }
455 }
456
457 #[inline]
458 fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
459 where
460 P: FnMut(&Self::Item) -> bool,
461 I: DoubleEndedIterator,
462 {
463 self.iter.as_mut()?.rfind(predicate)
464 }
465}
466
467#[cfg(not(feature = "ferrocene_subset"))]
469#[unstable(issue = "none", feature = "inplace_iteration")]
470unsafe impl<I> SourceIter for Fuse<I>
471where
472 I: SourceIter + TrustedFused,
473{
474 type Source = I::Source;
475
476 #[inline]
477 unsafe fn as_inner(&mut self) -> &mut I::Source {
478 unsafe { SourceIter::as_inner(self.iter.as_mut().unwrap_unchecked()) }
482 }
483}
484
485#[cfg(not(feature = "ferrocene_subset"))]
486#[inline]
487fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> {
488 let x = f(opt.as_mut()?);
489 if x.is_none() {
490 *opt = None;
491 }
492 x
493}