use super::Peekable; /// An iterator adapter that places a separator between all elements. /// /// This `struct` is created by [`Iterator::intersperse`]. See its documentation /// for more information. #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] #[derive(Debug, Clone)] pub struct Intersperse where I::Item: Clone, { separator: I::Item, iter: Peekable, needs_sep: bool, } impl Intersperse where I::Item: Clone, { pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self { Self { iter: iter.peekable(), separator, needs_sep: false } } } #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] impl Iterator for Intersperse where I: Iterator, I::Item: Clone, { type Item = I::Item; #[inline] fn next(&mut self) -> Option { if self.needs_sep && self.iter.peek().is_some() { self.needs_sep = false; Some(self.separator.clone()) } else { self.needs_sep = true; self.iter.next() } } fn fold(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { let separator = self.separator; intersperse_fold(self.iter, init, f, move || separator.clone(), self.needs_sep) } fn size_hint(&self) -> (usize, Option) { intersperse_size_hint(&self.iter, self.needs_sep) } } /// An iterator adapter that places a separator between all elements. /// /// This `struct` is created by [`Iterator::intersperse_with`]. See its /// documentation for more information. #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] pub struct IntersperseWith where I: Iterator, { separator: G, iter: Peekable, needs_sep: bool, } #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] impl crate::fmt::Debug for IntersperseWith where I: Iterator + crate::fmt::Debug, I::Item: crate::fmt::Debug, G: crate::fmt::Debug, { fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result { f.debug_struct("IntersperseWith") .field("separator", &self.separator) .field("iter", &self.iter) .field("needs_sep", &self.needs_sep) .finish() } } #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] impl crate::clone::Clone for IntersperseWith where I: Iterator + crate::clone::Clone, I::Item: crate::clone::Clone, G: Clone, { fn clone(&self) -> Self { IntersperseWith { separator: self.separator.clone(), iter: self.iter.clone(), needs_sep: self.needs_sep.clone(), } } } impl IntersperseWith where I: Iterator, G: FnMut() -> I::Item, { pub(in crate::iter) fn new(iter: I, separator: G) -> Self { Self { iter: iter.peekable(), separator, needs_sep: false } } } #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] impl Iterator for IntersperseWith where I: Iterator, G: FnMut() -> I::Item, { type Item = I::Item; #[inline] fn next(&mut self) -> Option { if self.needs_sep && self.iter.peek().is_some() { self.needs_sep = false; Some((self.separator)()) } else { self.needs_sep = true; self.iter.next() } } fn fold(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { intersperse_fold(self.iter, init, f, self.separator, self.needs_sep) } fn size_hint(&self) -> (usize, Option) { intersperse_size_hint(&self.iter, self.needs_sep) } } fn intersperse_size_hint(iter: &I, needs_sep: bool) -> (usize, Option) where I: Iterator, { let (lo, hi) = iter.size_hint(); let next_is_elem = !needs_sep; ( lo.saturating_sub(next_is_elem as usize).saturating_add(lo), hi.and_then(|hi| hi.saturating_sub(next_is_elem as usize).checked_add(hi)), ) } fn intersperse_fold( mut iter: I, init: B, mut f: F, mut separator: G, needs_sep: bool, ) -> B where I: Iterator, F: FnMut(B, I::Item) -> B, G: FnMut() -> I::Item, { let mut accum = init; if !needs_sep { if let Some(x) = iter.next() { accum = f(accum, x); } else { return accum; } } iter.fold(accum, |mut accum, x| { accum = f(accum, separator()); accum = f(accum, x); accum }) }