use std::iter::{Fuse, FusedIterator}; use super::size_hint; pub trait IntersperseElement { fn generate(&mut self) -> Item; } #[derive(Debug, Clone)] pub struct IntersperseElementSimple(Item); impl IntersperseElement for IntersperseElementSimple { fn generate(&mut self) -> Item { self.0.clone() } } /// An iterator adaptor to insert a particular value /// between each element of the adapted iterator. /// /// Iterator element type is `I::Item` /// /// This iterator is *fused*. /// /// See [`.intersperse()`](crate::Itertools::intersperse) for more information. pub type Intersperse = IntersperseWith::Item>>; /// Create a new Intersperse iterator pub fn intersperse(iter: I, elt: I::Item) -> Intersperse where I: Iterator, { intersperse_with(iter, IntersperseElementSimple(elt)) } implItem> IntersperseElement for F { fn generate(&mut self) -> Item { self() } } /// An iterator adaptor to insert a particular value created by a function /// between each element of the adapted iterator. /// /// Iterator element type is `I::Item` /// /// This iterator is *fused*. /// /// See [`.intersperse_with()`](crate::Itertools::intersperse_with) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[derive(Clone, Debug)] pub struct IntersperseWith where I: Iterator, { element: ElemF, iter: Fuse, peek: Option, } /// Create a new `IntersperseWith` iterator pub fn intersperse_with(iter: I, elt: ElemF) -> IntersperseWith where I: Iterator, { let mut iter = iter.fuse(); IntersperseWith { peek: iter.next(), iter, element: elt, } } impl Iterator for IntersperseWith where I: Iterator, ElemF: IntersperseElement { type Item = I::Item; #[inline] fn next(&mut self) -> Option { if self.peek.is_some() { self.peek.take() } else { self.peek = self.iter.next(); if self.peek.is_some() { Some(self.element.generate()) } else { None } } } fn size_hint(&self) -> (usize, Option) { // 2 * SH + { 1 or 0 } let has_peek = self.peek.is_some() as usize; let sh = self.iter.size_hint(); size_hint::add_scalar(size_hint::add(sh, sh), has_peek) } fn fold(mut self, init: B, mut f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { let mut accum = init; if let Some(x) = self.peek.take() { accum = f(accum, x); } let element = &mut self.element; self.iter.fold(accum, |accum, x| { let accum = f(accum, element.generate()); f(accum, x) }) } } impl FusedIterator for IntersperseWith where I: Iterator, ElemF: IntersperseElement {}