pub(super) struct CharReader<I: Iterator> {
iter: std::iter::Peekable<I>,
taken: Option<I::Item>,
}
impl<I: Iterator> CharReader<I> {
pub(super) fn new(iter: I) -> Self {
Self {
iter: iter.peekable(),
taken: None,
}
}
pub(super) fn peek(&mut self) -> Option<&I::Item> {
match &self.taken {
Some(item) => Some(item),
None => self.iter.peek(),
}
}
pub(super) fn peek_second(&mut self) -> Option<&I::Item> {
if self.taken.is_none() {
self.taken = Some(self.iter.next()?);
}
self.iter.peek()
}
}
impl<I: Iterator> Iterator for CharReader<I> {
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
self.taken.take().or_else(|| self.iter.next())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn peeks_up_to_two_ahead() {
let mut reader = CharReader::new("ab".chars());
assert_eq!(reader.peek_second(), Some(&'b'));
assert_eq!(reader.peek(), Some(&'a'));
assert_eq!(reader.next(), Some('a'));
assert_eq!(reader.peek_second(), None);
assert_eq!(reader.peek(), Some(&'b'));
assert_eq!(reader.next(), Some('b'));
assert_eq!(reader.peek(), None);
assert_eq!(reader.peek_second(), None);
assert_eq!(reader.next(), None);
}
}