use crate::fmt; use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map, TrustedLen}; use crate::ops::Try; /// 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)) } } } #[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) } } #[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) } } #[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: TrustedLen, F: FnMut(I::Item) -> [T; N], { } #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, T, I, F, const N: usize> TrustedLen for FlatMap where I: TrustedLen, F: FnMut(I::Item) -> &'a [T; N], { } #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, T, I, F, const N: usize> TrustedLen for FlatMap where I: TrustedLen, F: FnMut(I::Item) -> &'a mut [T; N], { } /// 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) } } #[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) } } #[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: TrustedLen, ::Item: TrustedConstSize, { } /// Real logic of both `Flatten` and `FlatMap` which simply delegate to /// this type. #[derive(Clone, Debug)] 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 Iterator for FlattenCompat where I: Iterator>, U: Iterator, { type Item = U::Item; #[inline] 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] 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] fn try_fold(&mut self, mut init: Acc, mut fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { #[inline] fn flatten<'a, T: IntoIterator, Acc, R: Try>( frontiter: &'a mut Option, fold: &'a mut impl FnMut(Acc, T::Item) -> R, ) -> impl FnMut(Acc, T) -> R + 'a { move |acc, x| { let mut mid = x.into_iter(); let r = mid.try_fold(acc, &mut *fold); *frontiter = Some(mid); r } } if let Some(ref mut front) = self.frontiter { init = front.try_fold(init, &mut fold)?; } self.frontiter = None; init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?; self.frontiter = None; if let Some(ref mut back) = self.backiter { init = back.try_fold(init, &mut fold)?; } self.backiter = None; try { init } } #[inline] fn fold(self, mut init: Acc, mut fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { #[inline] fn flatten( fold: &mut impl FnMut(Acc, T::Item) -> Acc, ) -> impl FnMut(Acc, T) -> Acc + '_ { move |acc, x| x.into_iter().fold(acc, &mut *fold) } if let Some(front) = self.frontiter { init = front.fold(init, &mut fold); } init = self.iter.fold(init, flatten(&mut fold)); if let Some(back) = self.backiter { init = back.fold(init, &mut fold); } init } #[inline] #[rustc_inherit_overflow_checks] fn advance_by(&mut self, n: usize) -> Result<(), usize> { let mut rem = n; loop { if let Some(ref mut front) = self.frontiter { match front.advance_by(rem) { ret @ Ok(_) => return ret, Err(advanced) => rem -= advanced, } } self.frontiter = match self.iter.next() { Some(iterable) => Some(iterable.into_iter()), _ => break, } } self.frontiter = None; if let Some(ref mut back) = self.backiter { match back.advance_by(rem) { ret @ Ok(_) => return ret, Err(advanced) => rem -= advanced, } } if rem > 0 { return Err(n - rem); } self.backiter = None; Ok(()) } } impl DoubleEndedIterator for FlattenCompat where I: DoubleEndedIterator>, U: DoubleEndedIterator, { #[inline] 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] fn try_rfold(&mut self, mut init: Acc, mut fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { #[inline] fn flatten<'a, T: IntoIterator, Acc, R: Try>( backiter: &'a mut Option, fold: &'a mut impl FnMut(Acc, T::Item) -> R, ) -> impl FnMut(Acc, T) -> R + 'a where T::IntoIter: DoubleEndedIterator, { move |acc, x| { let mut mid = x.into_iter(); let r = mid.try_rfold(acc, &mut *fold); *backiter = Some(mid); r } } if let Some(ref mut back) = self.backiter { init = back.try_rfold(init, &mut fold)?; } self.backiter = None; init = self.iter.try_rfold(init, flatten(&mut self.backiter, &mut fold))?; self.backiter = None; if let Some(ref mut front) = self.frontiter { init = front.try_rfold(init, &mut fold)?; } self.frontiter = None; try { init } } #[inline] fn rfold(self, mut init: Acc, mut fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { #[inline] fn flatten( fold: &mut impl FnMut(Acc, T::Item) -> Acc, ) -> impl FnMut(Acc, T) -> Acc + '_ where T::IntoIter: DoubleEndedIterator, { move |acc, x| x.into_iter().rfold(acc, &mut *fold) } if let Some(back) = self.backiter { init = back.rfold(init, &mut fold); } init = self.iter.rfold(init, flatten(&mut fold)); if let Some(front) = self.frontiter { init = front.rfold(init, &mut fold); } init } #[inline] #[rustc_inherit_overflow_checks] fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { let mut rem = n; loop { if let Some(ref mut back) = self.backiter { match back.advance_back_by(rem) { ret @ Ok(_) => return ret, Err(advanced) => rem -= advanced, } } match self.iter.next_back() { Some(iterable) => self.backiter = Some(iterable.into_iter()), _ => break, } } self.backiter = None; if let Some(ref mut front) = self.frontiter { match front.advance_back_by(rem) { ret @ Ok(_) => return ret, Err(advanced) => rem -= advanced, } } if rem > 0 { return Err(n - rem); } self.frontiter = None; Ok(()) } } 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) } } #[doc(hidden)] #[unstable(feature = "std_internals", issue = "none")] // FIXME(#20400): Instead of this helper trait there should be multiple impl TrustedLen for Flatten<> // blocks with different bounds on Iterator::Item but the compiler erroneously considers them overlapping pub unsafe trait TrustedConstSize: IntoIterator {} #[unstable(feature = "std_internals", issue = "none")] unsafe impl TrustedConstSize for [T; N] {} #[unstable(feature = "std_internals", issue = "none")] unsafe impl TrustedConstSize for &'_ [T; N] {} #[unstable(feature = "std_internals", issue = "none")] unsafe impl TrustedConstSize for &'_ mut [T; 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 }