use crate::intrinsics; use crate::iter::{ DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedRandomAccess, }; use crate::ops::Try; /// An iterator that yields `None` forever after the underlying iterator /// yields `None` once. /// /// This `struct` is created by the [`fuse`] method on [`Iterator`]. See its /// documentation for more. /// /// [`fuse`]: trait.Iterator.html#method.fuse /// [`Iterator`]: trait.Iterator.html #[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`, this is always assumed `Some`! 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 {} /// Fuse the iterator if the expression is `None`. macro_rules! fuse { ($self:ident . iter . $($call:tt)+) => { match $self.iter { Some(ref mut iter) => match iter.$($call)+ { None => { $self.iter = None; None } item => item, }, None => None, } }; } // NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`. // Implementing this as a directly-expanded macro helps codegen performance. macro_rules! unchecked { ($self:ident) => { match $self { Fuse { iter: Some(iter) } => iter, // SAFETY: the specialized iterator never sets `None` Fuse { iter: None } => unsafe { intrinsics::unreachable() }, } }; } // Any 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 { FuseImpl::last(self) } #[inline] fn count(self) -> usize { FuseImpl::count(self) } #[inline] fn size_hint(&self) -> (usize, Option) { FuseImpl::size_hint(self) } #[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, acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { FuseImpl::fold(self, acc, fold) } #[inline] fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, { FuseImpl::find(self, predicate) } } #[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, acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { FuseImpl::rfold(self, acc, fold) } #[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 { FuseImpl::len(self) } fn is_empty(&self) -> bool { FuseImpl::is_empty(self) } } unsafe impl TrustedRandomAccess for Fuse where I: TrustedRandomAccess, { unsafe fn get_unchecked(&mut self, i: usize) -> I::Item { match self.iter { Some(ref mut iter) => iter.get_unchecked(i), // SAFETY: the caller asserts there is an item at `i`, so we're not exhausted. None => intrinsics::unreachable(), } } fn may_have_side_effect() -> bool { I::may_have_side_effect() } } // Fuse specialization trait #[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 last(self) -> Option; fn count(self) -> usize; fn size_hint(&self) -> (usize, Option); fn try_fold(&mut self, acc: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try; fn fold(self, acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc; 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 rfold(self, acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, I: DoubleEndedIterator; fn rfind

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, I: DoubleEndedIterator; // Functions specific to ExactSizeIterator fn len(&self) -> usize where I: ExactSizeIterator; fn is_empty(&self) -> bool where I: ExactSizeIterator; } // General Fuse impl #[doc(hidden)] impl FuseImpl for Fuse where I: Iterator, { type Item = ::Item; #[inline] default fn next(&mut self) -> Option<::Item> { fuse!(self.iter.next()) } #[inline] default fn nth(&mut self, n: usize) -> Option { fuse!(self.iter.nth(n)) } #[inline] default fn last(self) -> Option { match self.iter { Some(iter) => iter.last(), None => None, } } #[inline] default fn count(self) -> usize { match self.iter { Some(iter) => iter.count(), None => 0, } } #[inline] default fn size_hint(&self) -> (usize, Option) { match self.iter { Some(ref iter) => iter.size_hint(), None => (0, Some(0)), } } #[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::from_ok(acc) } #[inline] default 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] default fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, { fuse!(self.iter.find(predicate)) } #[inline] default fn next_back(&mut self) -> Option<::Item> where I: DoubleEndedIterator, { fuse!(self.iter.next_back()) } #[inline] default fn nth_back(&mut self, n: usize) -> Option<::Item> where I: DoubleEndedIterator, { fuse!(self.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::from_ok(acc) } #[inline] default fn rfold(self, mut acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, I: DoubleEndedIterator, { if let Some(iter) = self.iter { acc = iter.rfold(acc, fold); } acc } #[inline] default fn rfind

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, I: DoubleEndedIterator, { fuse!(self.iter.rfind(predicate)) } #[inline] default fn len(&self) -> usize where I: ExactSizeIterator, { match self.iter { Some(ref iter) => iter.len(), None => 0, } } #[inline] default fn is_empty(&self) -> bool where I: ExactSizeIterator, { match self.iter { Some(ref iter) => iter.is_empty(), None => true, } } } #[doc(hidden)] impl FuseImpl for Fuse where I: FusedIterator, { #[inline] fn next(&mut self) -> Option<::Item> { unchecked!(self).next() } #[inline] fn nth(&mut self, n: usize) -> Option { unchecked!(self).nth(n) } #[inline] fn last(self) -> Option { unchecked!(self).last() } #[inline] fn count(self) -> usize { unchecked!(self).count() } #[inline] fn size_hint(&self) -> (usize, Option) { unchecked!(self).size_hint() } #[inline] fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { unchecked!(self).try_fold(init, fold) } #[inline] fn fold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { unchecked!(self).fold(init, fold) } #[inline] fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, { unchecked!(self).find(predicate) } #[inline] fn next_back(&mut self) -> Option<::Item> where I: DoubleEndedIterator, { unchecked!(self).next_back() } #[inline] fn nth_back(&mut self, n: usize) -> Option<::Item> where I: DoubleEndedIterator, { unchecked!(self).nth_back(n) } #[inline] fn try_rfold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, I: DoubleEndedIterator, { unchecked!(self).try_rfold(init, fold) } #[inline] fn rfold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, I: DoubleEndedIterator, { unchecked!(self).rfold(init, fold) } #[inline] fn rfind

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, I: DoubleEndedIterator, { unchecked!(self).rfind(predicate) } #[inline] fn len(&self) -> usize where I: ExactSizeIterator, { unchecked!(self).len() } #[inline] fn is_empty(&self) -> bool where I: ExactSizeIterator, { unchecked!(self).is_empty() } }