use crate::intrinsics; use crate::iter::adapters::zip::try_get_unchecked; use crate::iter::{ DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, }; use crate::ops::Try; /// An iterator that yields `None` forever after the underlying iterator /// yields `None` once. /// /// This `struct` is created by [`Iterator::fuse`]. See its documentation /// for more. #[derive(Clone, Debug)] #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Fuse { // NOTE: for `I: FusedIterator`, we never bother setting `None`, but // we still have to be prepared for that state due to variance. // See rust-lang/rust#85863 iter: Option, } impl Fuse { pub(in crate::iter) fn new(iter: I) -> Fuse { Fuse { iter: Some(iter) } } } #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Fuse where I: Iterator {} // Any specialized implementation here is made internal // to avoid exposing default fns outside this trait. #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Fuse where I: Iterator, { type Item = ::Item; #[inline] fn next(&mut self) -> Option { FuseImpl::next(self) } #[inline] fn nth(&mut self, n: usize) -> Option { FuseImpl::nth(self, n) } #[inline] fn last(self) -> Option { match self.iter { Some(iter) => iter.last(), None => None, } } #[inline] fn count(self) -> usize { match self.iter { Some(iter) => iter.count(), None => 0, } } #[inline] fn size_hint(&self) -> (usize, Option) { match self.iter { Some(ref iter) => iter.size_hint(), None => (0, Some(0)), } } #[inline] fn try_fold(&mut self, acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { FuseImpl::try_fold(self, acc, fold) } #[inline] fn fold(self, mut acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { if let Some(iter) = self.iter { acc = iter.fold(acc, fold); } acc } #[inline] fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, { FuseImpl::find(self, predicate) } #[inline] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item where Self: TrustedRandomAccessNoCoerce, { match self.iter { // SAFETY: the caller must uphold the contract for // `Iterator::__iterator_get_unchecked`. Some(ref mut iter) => unsafe { try_get_unchecked(iter, idx) }, // SAFETY: the caller asserts there is an item at `i`, so we're not exhausted. None => unsafe { intrinsics::unreachable() }, } } } #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for Fuse where I: DoubleEndedIterator, { #[inline] fn next_back(&mut self) -> Option<::Item> { FuseImpl::next_back(self) } #[inline] fn nth_back(&mut self, n: usize) -> Option<::Item> { FuseImpl::nth_back(self, n) } #[inline] fn try_rfold(&mut self, acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { FuseImpl::try_rfold(self, acc, fold) } #[inline] fn rfold(self, mut acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { if let Some(iter) = self.iter { acc = iter.rfold(acc, fold); } acc } #[inline] fn rfind

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, { FuseImpl::rfind(self, predicate) } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Fuse where I: ExactSizeIterator, { fn len(&self) -> usize { match self.iter { Some(ref iter) => iter.len(), None => 0, } } fn is_empty(&self) -> bool { match self.iter { Some(ref iter) => iter.is_empty(), None => true, } } } #[unstable(feature = "trusted_len", issue = "37572")] // SAFETY: `TrustedLen` requires that an accurate length is reported via `size_hint()`. As `Fuse` // is just forwarding this to the wrapped iterator `I` this property is preserved and it is safe to // implement `TrustedLen` here. unsafe impl TrustedLen for Fuse where I: TrustedLen {} #[doc(hidden)] #[unstable(feature = "trusted_random_access", issue = "none")] // SAFETY: `TrustedRandomAccess` requires that `size_hint()` must be exact and cheap to call, and // `Iterator::__iterator_get_unchecked()` must be implemented accordingly. // // This is safe to implement as `Fuse` is just forwarding these to the wrapped iterator `I`, which // preserves these properties. unsafe impl TrustedRandomAccess for Fuse where I: TrustedRandomAccess {} #[doc(hidden)] #[unstable(feature = "trusted_random_access", issue = "none")] unsafe impl TrustedRandomAccessNoCoerce for Fuse where I: TrustedRandomAccessNoCoerce, { const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT; } /// Fuse specialization trait /// /// We only need to worry about `&mut self` methods, which /// may exhaust the iterator without consuming it. #[doc(hidden)] trait FuseImpl { type Item; // Functions specific to any normal Iterators fn next(&mut self) -> Option; fn nth(&mut self, n: usize) -> Option; fn try_fold(&mut self, acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try; fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool; // Functions specific to DoubleEndedIterators fn next_back(&mut self) -> Option where I: DoubleEndedIterator; fn nth_back(&mut self, n: usize) -> Option where I: DoubleEndedIterator; fn try_rfold(&mut self, acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, I: DoubleEndedIterator; fn rfind

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, I: DoubleEndedIterator; } /// General `Fuse` impl which sets `iter = None` when exhausted. #[doc(hidden)] impl FuseImpl for Fuse where I: Iterator, { type Item = ::Item; #[inline] default fn next(&mut self) -> Option<::Item> { and_then_or_clear(&mut self.iter, Iterator::next) } #[inline] default fn nth(&mut self, n: usize) -> Option { and_then_or_clear(&mut self.iter, |iter| iter.nth(n)) } #[inline] default fn try_fold(&mut self, mut acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { if let Some(ref mut iter) = self.iter { acc = iter.try_fold(acc, fold)?; self.iter = None; } try { acc } } #[inline] default fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, { and_then_or_clear(&mut self.iter, |iter| iter.find(predicate)) } #[inline] default fn next_back(&mut self) -> Option<::Item> where I: DoubleEndedIterator, { and_then_or_clear(&mut self.iter, |iter| iter.next_back()) } #[inline] default fn nth_back(&mut self, n: usize) -> Option<::Item> where I: DoubleEndedIterator, { and_then_or_clear(&mut self.iter, |iter| iter.nth_back(n)) } #[inline] default fn try_rfold(&mut self, mut acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, I: DoubleEndedIterator, { if let Some(ref mut iter) = self.iter { acc = iter.try_rfold(acc, fold)?; self.iter = None; } try { acc } } #[inline] default fn rfind

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, I: DoubleEndedIterator, { and_then_or_clear(&mut self.iter, |iter| iter.rfind(predicate)) } } /// Specialized `Fuse` impl which doesn't bother clearing `iter` when exhausted. /// However, we must still be prepared for the possibility that it was already cleared! #[doc(hidden)] impl FuseImpl for Fuse where I: FusedIterator, { #[inline] fn next(&mut self) -> Option<::Item> { self.iter.as_mut()?.next() } #[inline] fn nth(&mut self, n: usize) -> Option { self.iter.as_mut()?.nth(n) } #[inline] fn try_fold(&mut self, mut acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { if let Some(ref mut iter) = self.iter { acc = iter.try_fold(acc, fold)?; } try { acc } } #[inline] fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, { self.iter.as_mut()?.find(predicate) } #[inline] fn next_back(&mut self) -> Option<::Item> where I: DoubleEndedIterator, { self.iter.as_mut()?.next_back() } #[inline] fn nth_back(&mut self, n: usize) -> Option<::Item> where I: DoubleEndedIterator, { self.iter.as_mut()?.nth_back(n) } #[inline] fn try_rfold(&mut self, mut acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, I: DoubleEndedIterator, { if let Some(ref mut iter) = self.iter { acc = iter.try_rfold(acc, fold)?; } try { acc } } #[inline] fn rfind

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, I: DoubleEndedIterator, { self.iter.as_mut()?.rfind(predicate) } } #[inline] fn and_then_or_clear(opt: &mut Option, f: impl FnOnce(&mut T) -> Option) -> Option { let x = f(opt.as_mut()?); if x.is_none() { *opt = None; } x }