use crate::iter::adapters::SourceIter; use crate::iter::{ Cloned, Copied, Empty, Filter, FilterMap, Fuse, FusedIterator, Map, Once, OnceWith, TrustedFused, TrustedLen, }; use crate::num::NonZero; use crate::ops::{ControlFlow, Try}; use crate::{array, fmt, option, result}; /// An iterator that maps each element to an iterator, and yields the elements /// of the produced iterators. /// /// This `struct` is created by [`Iterator::flat_map`]. See its documentation /// for more. #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct FlatMap { inner: FlattenCompat, ::IntoIter>, } impl U> FlatMap { pub(in crate::iter) fn new(iter: I, f: F) -> FlatMap { FlatMap { inner: FlattenCompat::new(iter.map(f)) } } pub(crate) fn into_parts(self) -> (Option, Option, Option) { ( self.inner.frontiter, self.inner.iter.into_inner().map(Map::into_inner), self.inner.backiter, ) } } #[stable(feature = "rust1", since = "1.0.0")] impl Clone for FlatMap where U: Clone + IntoIterator, { fn clone(&self) -> Self { FlatMap { inner: self.inner.clone() } } } #[stable(feature = "core_impl_debug", since = "1.9.0")] impl fmt::Debug for FlatMap where U: IntoIterator, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("FlatMap").field("inner", &self.inner).finish() } } #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for FlatMap where F: FnMut(I::Item) -> U, { type Item = U::Item; #[inline] fn next(&mut self) -> Option { self.inner.next() } #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } #[inline] fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { self.inner.try_fold(init, fold) } #[inline] fn fold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { self.inner.fold(init, fold) } #[inline] fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { self.inner.advance_by(n) } #[inline] fn count(self) -> usize { self.inner.count() } #[inline] fn last(self) -> Option { self.inner.last() } } #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for FlatMap where F: FnMut(I::Item) -> U, U: IntoIterator, { #[inline] fn next_back(&mut self) -> Option { self.inner.next_back() } #[inline] fn try_rfold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { self.inner.try_rfold(init, fold) } #[inline] fn rfold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { self.inner.rfold(init, fold) } #[inline] fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { self.inner.advance_back_by(n) } } #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for FlatMap where I: FusedIterator, U: IntoIterator, F: FnMut(I::Item) -> U, { } #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for FlatMap where I: Iterator, U: IntoIterator, F: FnMut(I::Item) -> U, FlattenCompat, ::IntoIter>: TrustedLen, { } #[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl SourceIter for FlatMap where I: SourceIter + TrustedFused, U: IntoIterator, { type Source = I::Source; #[inline] unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.inner.iter) } } } /// An iterator that flattens one level of nesting in an iterator of things /// that can be turned into iterators. /// /// This `struct` is created by the [`flatten`] method on [`Iterator`]. See its /// documentation for more. /// /// [`flatten`]: Iterator::flatten() #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "iterator_flatten", since = "1.29.0")] pub struct Flatten> { inner: FlattenCompat::IntoIter>, } impl> Flatten { pub(in super::super) fn new(iter: I) -> Flatten { Flatten { inner: FlattenCompat::new(iter) } } } #[stable(feature = "iterator_flatten", since = "1.29.0")] impl fmt::Debug for Flatten where I: fmt::Debug + Iterator>, U: fmt::Debug + Iterator, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Flatten").field("inner", &self.inner).finish() } } #[stable(feature = "iterator_flatten", since = "1.29.0")] impl Clone for Flatten where I: Clone + Iterator>, U: Clone + Iterator, { fn clone(&self) -> Self { Flatten { inner: self.inner.clone() } } } #[stable(feature = "iterator_flatten", since = "1.29.0")] impl Iterator for Flatten where I: Iterator>, U: Iterator, { type Item = U::Item; #[inline] fn next(&mut self) -> Option { self.inner.next() } #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } #[inline] fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { self.inner.try_fold(init, fold) } #[inline] fn fold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { self.inner.fold(init, fold) } #[inline] fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { self.inner.advance_by(n) } #[inline] fn count(self) -> usize { self.inner.count() } #[inline] fn last(self) -> Option { self.inner.last() } } #[stable(feature = "iterator_flatten", since = "1.29.0")] impl DoubleEndedIterator for Flatten where I: DoubleEndedIterator>, U: DoubleEndedIterator, { #[inline] fn next_back(&mut self) -> Option { self.inner.next_back() } #[inline] fn try_rfold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { self.inner.try_rfold(init, fold) } #[inline] fn rfold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { self.inner.rfold(init, fold) } #[inline] fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { self.inner.advance_back_by(n) } } #[stable(feature = "iterator_flatten", since = "1.29.0")] impl FusedIterator for Flatten where I: FusedIterator>, U: Iterator, { } #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Flatten where I: Iterator, FlattenCompat::IntoIter>: TrustedLen, { } #[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl SourceIter for Flatten where I: SourceIter + TrustedFused + Iterator, ::Item: IntoIterator, { type Source = I::Source; #[inline] unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.inner.iter) } } } #[stable(feature = "default_iters", since = "1.70.0")] impl Default for Flatten where I: Default + Iterator, { /// Creates a `Flatten` iterator from the default value of `I`. /// /// ``` /// # use core::slice; /// # use std::iter::Flatten; /// let iter: Flatten> = Default::default(); /// assert_eq!(iter.count(), 0); /// ``` fn default() -> Self { Flatten::new(Default::default()) } } /// Real logic of both `Flatten` and `FlatMap` which simply delegate to /// this type. #[derive(Clone, Debug)] #[unstable(feature = "trusted_len", issue = "37572")] struct FlattenCompat { iter: Fuse, frontiter: Option, backiter: Option, } impl FlattenCompat where I: Iterator, { /// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`. fn new(iter: I) -> FlattenCompat { FlattenCompat { iter: iter.fuse(), frontiter: None, backiter: None } } } impl FlattenCompat where I: Iterator>, { /// Folds the inner iterators into an accumulator by applying an operation. /// /// Folds over the inner iterators, not over their elements. Is used by the `fold`, `count`, /// and `last` methods. #[inline] fn iter_fold(self, mut acc: Acc, mut fold: Fold) -> Acc where Fold: FnMut(Acc, U) -> Acc, { #[inline] fn flatten( fold: &mut impl FnMut(Acc, T::IntoIter) -> Acc, ) -> impl FnMut(Acc, T) -> Acc + '_ { move |acc, iter| fold(acc, iter.into_iter()) } if let Some(iter) = self.frontiter { acc = fold(acc, iter); } acc = self.iter.fold(acc, flatten(&mut fold)); if let Some(iter) = self.backiter { acc = fold(acc, iter); } acc } /// Folds over the inner iterators as long as the given function returns successfully, /// always storing the most recent inner iterator in `self.frontiter`. /// /// Folds over the inner iterators, not over their elements. Is used by the `try_fold` and /// `advance_by` methods. #[inline] fn iter_try_fold(&mut self, mut acc: Acc, mut fold: Fold) -> R where Fold: FnMut(Acc, &mut U) -> R, R: Try, { #[inline] fn flatten<'a, T: IntoIterator, Acc, R: Try>( frontiter: &'a mut Option, fold: &'a mut impl FnMut(Acc, &mut T::IntoIter) -> R, ) -> impl FnMut(Acc, T) -> R + 'a { move |acc, iter| fold(acc, frontiter.insert(iter.into_iter())) } if let Some(iter) = &mut self.frontiter { acc = fold(acc, iter)?; } self.frontiter = None; acc = self.iter.try_fold(acc, flatten(&mut self.frontiter, &mut fold))?; self.frontiter = None; if let Some(iter) = &mut self.backiter { acc = fold(acc, iter)?; } self.backiter = None; try { acc } } } impl FlattenCompat where I: DoubleEndedIterator>, { /// Folds the inner iterators into an accumulator by applying an operation, starting form the /// back. /// /// Folds over the inner iterators, not over their elements. Is used by the `rfold` method. #[inline] fn iter_rfold(self, mut acc: Acc, mut fold: Fold) -> Acc where Fold: FnMut(Acc, U) -> Acc, { #[inline] fn flatten( fold: &mut impl FnMut(Acc, T::IntoIter) -> Acc, ) -> impl FnMut(Acc, T) -> Acc + '_ { move |acc, iter| fold(acc, iter.into_iter()) } if let Some(iter) = self.backiter { acc = fold(acc, iter); } acc = self.iter.rfold(acc, flatten(&mut fold)); if let Some(iter) = self.frontiter { acc = fold(acc, iter); } acc } /// Folds over the inner iterators in reverse order as long as the given function returns /// successfully, always storing the most recent inner iterator in `self.backiter`. /// /// Folds over the inner iterators, not over their elements. Is used by the `try_rfold` and /// `advance_back_by` methods. #[inline] fn iter_try_rfold(&mut self, mut acc: Acc, mut fold: Fold) -> R where Fold: FnMut(Acc, &mut U) -> R, R: Try, { #[inline] fn flatten<'a, T: IntoIterator, Acc, R: Try>( backiter: &'a mut Option, fold: &'a mut impl FnMut(Acc, &mut T::IntoIter) -> R, ) -> impl FnMut(Acc, T) -> R + 'a { move |acc, iter| fold(acc, backiter.insert(iter.into_iter())) } if let Some(iter) = &mut self.backiter { acc = fold(acc, iter)?; } self.backiter = None; acc = self.iter.try_rfold(acc, flatten(&mut self.backiter, &mut fold))?; self.backiter = None; if let Some(iter) = &mut self.frontiter { acc = fold(acc, iter)?; } self.frontiter = None; try { acc } } } // See also the `OneShot` specialization below. impl Iterator for FlattenCompat where I: Iterator>, U: Iterator, { type Item = U::Item; #[inline] default fn next(&mut self) -> Option { loop { if let elt @ Some(_) = and_then_or_clear(&mut self.frontiter, Iterator::next) { return elt; } match self.iter.next() { None => return and_then_or_clear(&mut self.backiter, Iterator::next), Some(inner) => self.frontiter = Some(inner.into_iter()), } } } #[inline] default fn size_hint(&self) -> (usize, Option) { let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint); let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint); let lo = flo.saturating_add(blo); if let Some(fixed_size) = <::Item as ConstSizeIntoIterator>::size() { let (lower, upper) = self.iter.size_hint(); let lower = lower.saturating_mul(fixed_size).saturating_add(lo); let upper = try { fhi?.checked_add(bhi?)?.checked_add(fixed_size.checked_mul(upper?)?)? }; return (lower, upper); } match (self.iter.size_hint(), fhi, bhi) { ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)), _ => (lo, None), } } #[inline] default fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { #[inline] fn flatten>( mut fold: impl FnMut(Acc, U::Item) -> R, ) -> impl FnMut(Acc, &mut U) -> R { move |acc, iter| iter.try_fold(acc, &mut fold) } self.iter_try_fold(init, flatten(fold)) } #[inline] default fn fold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { #[inline] fn flatten( mut fold: impl FnMut(Acc, U::Item) -> Acc, ) -> impl FnMut(Acc, U) -> Acc { move |acc, iter| iter.fold(acc, &mut fold) } self.iter_fold(init, flatten(fold)) } #[inline] #[rustc_inherit_overflow_checks] default fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { #[inline] #[rustc_inherit_overflow_checks] fn advance(n: usize, iter: &mut U) -> ControlFlow<(), usize> { match iter.advance_by(n) { Ok(()) => ControlFlow::Break(()), Err(remaining) => ControlFlow::Continue(remaining.get()), } } match self.iter_try_fold(n, advance) { ControlFlow::Continue(remaining) => NonZero::new(remaining).map_or(Ok(()), Err), _ => Ok(()), } } #[inline] default fn count(self) -> usize { #[inline] #[rustc_inherit_overflow_checks] fn count(acc: usize, iter: U) -> usize { acc + iter.count() } self.iter_fold(0, count) } #[inline] default fn last(self) -> Option { #[inline] fn last(last: Option, iter: U) -> Option { iter.last().or(last) } self.iter_fold(None, last) } } // See also the `OneShot` specialization below. impl DoubleEndedIterator for FlattenCompat where I: DoubleEndedIterator>, U: DoubleEndedIterator, { #[inline] default fn next_back(&mut self) -> Option { loop { if let elt @ Some(_) = and_then_or_clear(&mut self.backiter, |b| b.next_back()) { return elt; } match self.iter.next_back() { None => return and_then_or_clear(&mut self.frontiter, |f| f.next_back()), Some(inner) => self.backiter = Some(inner.into_iter()), } } } #[inline] default fn try_rfold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { #[inline] fn flatten>( mut fold: impl FnMut(Acc, U::Item) -> R, ) -> impl FnMut(Acc, &mut U) -> R { move |acc, iter| iter.try_rfold(acc, &mut fold) } self.iter_try_rfold(init, flatten(fold)) } #[inline] default fn rfold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { #[inline] fn flatten( mut fold: impl FnMut(Acc, U::Item) -> Acc, ) -> impl FnMut(Acc, U) -> Acc { move |acc, iter| iter.rfold(acc, &mut fold) } self.iter_rfold(init, flatten(fold)) } #[inline] #[rustc_inherit_overflow_checks] default fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { #[inline] #[rustc_inherit_overflow_checks] fn advance(n: usize, iter: &mut U) -> ControlFlow<(), usize> { match iter.advance_back_by(n) { Ok(()) => ControlFlow::Break(()), Err(remaining) => ControlFlow::Continue(remaining.get()), } } match self.iter_try_rfold(n, advance) { ControlFlow::Continue(remaining) => NonZero::new(remaining).map_or(Ok(()), Err), _ => Ok(()), } } } unsafe impl TrustedLen for FlattenCompat::IntoIter> where I: TrustedLen, { } unsafe impl<'a, const N: usize, I, T> TrustedLen for FlattenCompat::IntoIter> where I: TrustedLen, { } unsafe impl<'a, const N: usize, I, T> TrustedLen for FlattenCompat::IntoIter> where I: TrustedLen, { } trait ConstSizeIntoIterator: IntoIterator { // FIXME(#31844): convert to an associated const once specialization supports that fn size() -> Option; } impl ConstSizeIntoIterator for T where T: IntoIterator, { #[inline] default fn size() -> Option { None } } impl ConstSizeIntoIterator for [T; N] { #[inline] fn size() -> Option { Some(N) } } impl ConstSizeIntoIterator for &[T; N] { #[inline] fn size() -> Option { Some(N) } } impl ConstSizeIntoIterator for &mut [T; N] { #[inline] fn size() -> Option { Some(N) } } #[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 } /// Specialization trait for iterator types that never return more than one item. /// /// Note that we still have to deal with the possibility that the iterator was /// already exhausted before it came into our control. #[rustc_specialization_trait] trait OneShot {} // These all have exactly one item, if not already consumed. impl OneShot for Once {} impl OneShot for OnceWith {} impl OneShot for array::IntoIter {} impl OneShot for option::IntoIter {} impl OneShot for option::Iter<'_, T> {} impl OneShot for option::IterMut<'_, T> {} impl OneShot for result::IntoIter {} impl OneShot for result::Iter<'_, T> {} impl OneShot for result::IterMut<'_, T> {} // These are always empty, which is fine to optimize too. impl OneShot for Empty {} impl OneShot for array::IntoIter {} // These adapters never increase the number of items. // (There are more possible, but for now this matches BoundedSize above.) impl OneShot for Cloned {} impl OneShot for Copied {} impl OneShot for Filter {} impl OneShot for FilterMap {} impl OneShot for Map {} // Blanket impls pass this property through as well // (but we can't do `Box` unless we expose this trait to alloc) impl OneShot for &mut I {} #[inline] fn into_item(inner: I) -> Option where I: IntoIterator, { inner.into_iter().next() } #[inline] fn flatten_one, Acc>( mut fold: impl FnMut(Acc, I::Item) -> Acc, ) -> impl FnMut(Acc, I) -> Acc { move |acc, inner| match inner.into_iter().next() { Some(item) => fold(acc, item), None => acc, } } #[inline] fn try_flatten_one, Acc, R: Try>( mut fold: impl FnMut(Acc, I::Item) -> R, ) -> impl FnMut(Acc, I) -> R { move |acc, inner| match inner.into_iter().next() { Some(item) => fold(acc, item), None => try { acc }, } } #[inline] fn advance_by_one(n: NonZero, inner: I) -> Option> where I: IntoIterator, { match inner.into_iter().next() { Some(_) => NonZero::new(n.get() - 1), None => Some(n), } } // Specialization: When the inner iterator `U` never returns more than one item, the `frontiter` and // `backiter` states are a waste, because they'll always have already consumed their item. So in // this impl, we completely ignore them and just focus on `self.iter`, and we only call the inner // `U::next()` one time. // // It's mostly fine if we accidentally mix this with the more generic impls, e.g. by forgetting to // specialize one of the methods. If the other impl did set the front or back, we wouldn't see it // here, but it would be empty anyway; and if the other impl looked for a front or back that we // didn't bother setting, it would just see `None` (or a previous empty) and move on. // // An exception to that is `advance_by(0)` and `advance_back_by(0)`, where the generic impls may set // `frontiter` or `backiter` without consuming the item, so we **must** override those. impl Iterator for FlattenCompat where I: Iterator>, U: Iterator + OneShot, { #[inline] fn next(&mut self) -> Option { while let Some(inner) = self.iter.next() { if let item @ Some(_) = inner.into_iter().next() { return item; } } None } #[inline] fn size_hint(&self) -> (usize, Option) { let (lower, upper) = self.iter.size_hint(); match ::size() { Some(0) => (0, Some(0)), Some(1) => (lower, upper), _ => (0, upper), } } #[inline] fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { self.iter.try_fold(init, try_flatten_one(fold)) } #[inline] fn fold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { self.iter.fold(init, flatten_one(fold)) } #[inline] fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { if let Some(n) = NonZero::new(n) { self.iter.try_fold(n, advance_by_one).map_or(Ok(()), Err) } else { // Just advance the outer iterator self.iter.advance_by(0) } } #[inline] fn count(self) -> usize { self.iter.filter_map(into_item).count() } #[inline] fn last(self) -> Option { self.iter.filter_map(into_item).last() } } // Note: We don't actually care about `U: DoubleEndedIterator`, since forward and backward are the // same for a one-shot iterator, but we have to keep that to match the default specialization. impl DoubleEndedIterator for FlattenCompat where I: DoubleEndedIterator>, U: DoubleEndedIterator + OneShot, { #[inline] fn next_back(&mut self) -> Option { while let Some(inner) = self.iter.next_back() { if let item @ Some(_) = inner.into_iter().next() { return item; } } None } #[inline] fn try_rfold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { self.iter.try_rfold(init, try_flatten_one(fold)) } #[inline] fn rfold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { self.iter.rfold(init, flatten_one(fold)) } #[inline] fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { if let Some(n) = NonZero::new(n) { self.iter.try_rfold(n, advance_by_one).map_or(Ok(()), Err) } else { // Just advance the outer iterator self.iter.advance_back_by(0) } } }