use std::iter::Peekable; pub use self::take_while::PeekableTakeWhile; /// An iterator with a `peek()` that returns an optional reference to the next /// element. /// /// This trait is an extension of the `Peekable` type in the standard library. pub trait Peek: Iterator { /// Returns a reference to the [`next`] value without advancing the iterator. /// /// Like [`next`], if there is a value, it is wrapped in [`Some`]. But if /// iteration is over, [`None`] is returned. fn peek(&mut self) -> Option<&Self::Item>; } impl Peek for &mut I { fn peek(&mut self) -> Option<&Self::Item> { I::peek(self) } } impl Peek for Box<&mut dyn Peek> { fn peek(&mut self) -> Option<&Self::Item> { (**self).peek() } } impl Peek for Peekable { fn peek(&mut self) -> Option<&Self::Item> { Peekable::peek(self) } } pub trait PeekExt: Peek { /// Returns the [`next`] value and advance the iterator only if `pred` is true. fn next_if bool>( &mut self, pred: P, ) -> Option> { let i = self.peek()?; if pred(i) { Some(Ok(self.next().unwrap())) } else { Some(Err(self)) } } fn next_if_then< P: FnOnce(&Self::Item) -> bool, F: FnOnce(Self::Item) -> T, G: FnOnce(&mut Self) -> T, T, >( &mut self, pred: P, matched: F, unmatched: G, ) -> Option { let i = self.peek()?; if pred(i) { Some(matched(self.next().unwrap())) } else { Some(unmatched(self)) } } /// Advances the iterator only if the [`next`] item equals `val`. fn next_if_eq(&mut self, val: &T) -> Option> where Self::Item: PartialEq, { self.next_if(|i| PartialEq::eq(i, val)) .map(|r| r.map(|_| ()).map_err(|i| i.peek().unwrap())) } fn consume_if_next(&mut self, val: &T) -> bool where Self::Item: PartialEq, { self.next_if_eq(val).map(|r| r.is_ok()).unwrap_or(false) } /// Advance the iterator until `pred` is false, or `peek` returns [`None`]. fn advance_while bool>(&mut self, mut pred: P) { while self.next_if(&mut pred).map(|r| r.is_ok()).unwrap_or(false) { // Condition already loops for us } } } impl PeekExt for I {} mod take_while { use super::Peek; #[derive(Clone, Debug, Eq, PartialEq)] pub struct PeekableTakeWhile { inner: I, predicate: Option, } impl PeekableTakeWhile where I: Peek, F: FnMut(&::Item) -> bool, { pub fn new(iter: I, predicate: F) -> Self { Self { inner: iter, predicate: Some(predicate), } } } impl Iterator for PeekableTakeWhile where I: Peek, F: FnMut(&::Item) -> bool, { type Item = ::Item; fn next(&mut self) -> Option { // Can't inline because of lifetimes let inner = &mut self.inner; if self.predicate.as_mut().and_then(|p| inner.peek().map(p))? { self.inner.next() } else { self.predicate = None; None } } } impl Peek for PeekableTakeWhile where I: Peek, F: FnMut(&::Item) -> bool, { fn peek(&mut self) -> Option<&Self::Item> { let inner = &mut self.inner; self.predicate .as_mut() .and_then(move |p| inner.peek().filter(|i| p(i))) } } }