use std::iter::Iterator;
use std::mem;
pub struct Peepable<I>
where
I: Iterator,
{
iter: I,
next: Option<I::Item>,
}
impl<I: Iterator> Iterator for Peepable<I> {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
let mut next = self.iter.next();
mem::swap(&mut next, &mut self.next);
next
}
}
impl<I: Iterator> Peepable<I> {
pub fn new(mut iter: I) -> Peepable<I> {
let next = iter.next();
Peepable {
iter: iter,
next: next,
}
}
pub fn peep(&self) -> Option<&I::Item> {
match self.next {
Some(ref next) => Some(next),
None => None,
}
}
}
#[cfg(test)]
mod tests {
use super::Peepable;
#[test]
fn basic_peeping() {
let vec = vec![1, 2, 3];
let peeper: Peepable<_> = Peepable::new(vec.into_iter());
assert_eq!(peeper.peep(), Some(&1));
let mut peeper = peeper;
assert_eq!(peeper.peep(), Some(&1));
assert_eq!(peeper.peep(), Some(&1));
assert_eq!(peeper.next(), Some(1));
assert_eq!(peeper.peep(), Some(&2));
assert_eq!(peeper.next(), Some(2));
assert_eq!(peeper.next(), Some(3));
assert_eq!(peeper.next(), None);
assert_eq!(peeper.peep(), None);
}
#[test]
fn basic_iterator() {
let vec = vec![1, 2, 3];
let mut peepable = Peepable::new(vec.into_iter());
assert_eq!(peepable.next(), Some(1));
assert_eq!(peepable.next(), Some(2));
assert_eq!(peepable.next(), Some(3));
assert_eq!(peepable.next(), None);
assert_eq!(peepable.next(), None);
}
#[test]
fn has_iterator_tools() {
let iter = Peepable::new((0..4));
let sum: u8 = iter.filter(|x| x > &1).map(|x| x * x).sum();
assert_eq!(sum, 13);
}
}