#![doc(html_root_url = "https://docs.rs/duck/0.2.0")]
pub trait PeekingExt: Iterator + Sized where <Self as Iterator>::Item: Clone {
#[inline]
fn peeking(self) -> Goose<Self> {
Goose::new(self)
}
}
impl<I: Iterator> PeekingExt for I where <I as Iterator>::Item: Clone {}
pub trait Anatid: Iterator {
type PeekItem;
fn peek(&mut self) -> Option<Self::PeekItem>;
}
macro_rules! impl_iterator {
($T:ident) => {
impl<I: Iterator> Iterator for $T<I> {
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<I::Item> {
match self.peeked.take() {
Some(v) => v,
None => self.iter.next(),
}
}
#[inline]
fn count(mut self) -> usize {
match self.peeked.take() {
Some(None) => 0,
Some(Some(_)) => 1 + self.iter.count(),
None => self.iter.count(),
}
}
#[inline]
fn nth(&mut self, n: usize) -> Option<I::Item> {
match self.peeked.take() {
Some(ref mut v) if n == 0 => v.take(),
Some(None) => None,
Some(Some(_)) => self.iter.nth(n - 1),
None => self.iter.nth(n),
}
}
#[inline]
fn last(mut self) -> Option<I::Item> {
let peek_opt = match self.peeked.take() {
Some(None) => return None,
Some(v) => v,
None => None,
};
self.iter.last().or(peek_opt)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let peek_len = match self.peeked {
Some(None) => return (0, Some(0)),
Some(Some(_)) => 1,
None => 0,
};
let (lo, hi) = self.iter.size_hint();
let lo = lo.saturating_add(peek_len);
let hi = hi.and_then(|x| x.checked_add(peek_len));
(lo, hi)
}
}
impl<I: ExactSizeIterator> ExactSizeIterator for $T<I> {}
};
}
#[derive(Clone, Debug)]
pub struct Goose<I: Iterator> {
iter: I,
peeked: Option<Option<I::Item>>,
}
impl<I: Iterator> Goose<I> where I::Item: Clone {
#[inline]
fn new(iter: I) -> Self {
Goose { iter, peeked: None }
}
#[inline]
pub fn peek(&mut self) -> Option<I::Item> {
Anatid::peek(self)
}
#[inline]
pub fn peeking(self) -> Duck<Self> {
Duck::new(self)
}
}
impl_iterator!(Goose);
impl<I: Iterator> Anatid for Goose<I> where I::Item: Clone {
type PeekItem = I::Item;
#[inline]
fn peek(&mut self) -> Option<I::Item> {
if self.peeked.is_none() {
self.peeked = Some(self.iter.next());
}
match self.peeked {
Some(Some(ref value)) => Some(value.clone()),
Some(None) => None,
_ => unreachable!(),
}
}
}
#[derive(Clone, Debug)]
pub struct Duck<I: Iterator> {
iter: I,
peeked: Option<Option<I::Item>>,
}
impl<I: Anatid> Duck<I> where I::Item: Clone {
#[inline]
fn new(iter: I) -> Self {
Duck { iter, peeked: None }
}
#[inline]
pub fn peek(&mut self) -> Option<(I::Item, Option<I::PeekItem>)> {
Anatid::peek(self)
}
#[inline]
pub fn peeking(self) -> Duck<Self> {
Duck::new(self)
}
}
impl_iterator!(Duck);
impl<I: Anatid> Anatid for Duck<I> where I::Item: Clone {
type PeekItem = (I::Item, Option<I::PeekItem>);
#[inline]
fn peek(&mut self) -> Option<Self::PeekItem> {
if self.peeked.is_none() {
self.peeked = Some(self.iter.next());
}
match self.peeked {
Some(Some(ref value)) => Some((value.clone(), self.iter.peek())),
Some(None) => None,
_ => unreachable!(),
}
}
}
#[test]
fn simple() {
let iter = vec![0, 1, 2].into_iter();
let mut iter = iter.peeking().peeking().peeking();
assert_eq!(iter.peek(), Some((0, Some((1, Some(2))))));
assert_eq!(iter.next(), Some(0));
assert_eq!(iter.peek(), Some((1, Some((2, None)))));
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.peek(), Some((2, None)));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.peek(), None);
assert_eq!(iter.next(), None);
}