use std::iter::Fuse; use super::size_hint; #[derive(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()`](../trait.Itertools.html#method.intersperse) for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[derive(Debug)] pub struct Intersperse where I: Iterator { element: I::Item, iter: Fuse, peek: Option, } /// Create a new Intersperse iterator pub fn intersperse(iter: I, elt: I::Item) -> Intersperse where I: Iterator { let mut iter = iter.fuse(); Intersperse { peek: iter.next(), iter, element: elt, } } impl Iterator for Intersperse where I: Iterator, I::Item: Clone { 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.clone()) } 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 = &self.element; self.iter.fold(accum, |accum, x| { let accum = f(accum, element.clone()); let accum = f(accum, x); accum }) } }