extern crate alloc;
use alloc::collections::VecDeque;
use core::str::Chars;
use crate::iter::Peek;
pub struct Source<'a> {
iter: Chars<'a>,
src: &'a str,
pos: usize,
peeked: VecDeque<char>,
}
impl<'a> Source<'a> {
pub fn new(src: &'a str) -> Self {
Self {
iter: src.chars(),
src,
pos: 0,
peeked: VecDeque::new(),
}
}
#[inline]
pub fn pos(&self) -> usize {
self.pos
}
#[inline]
pub fn src(&self) -> &'a str {
self.src
}
#[inline]
pub fn peek(&mut self) -> Option<char> {
self.peek_nth(0)
}
pub fn peek_nth(&mut self, nth: usize) -> Option<char> {
self.peeked.extend(
self.iter
.by_ref()
.take((nth + 1).saturating_sub(self.peeked.len())),
);
self.peeked.get(nth).copied()
}
}
impl<'a> Iterator for Source<'a> {
type Item = char;
fn next(&mut self) -> Option<Self::Item> {
self.peeked
.pop_front()
.or_else(|| self.iter.next())
.map(|c| {
self.pos += c.len_utf8();
c
})
}
}
impl<'a> Peek for Source<'a> {
type Item = char;
#[inline]
fn peek(&mut self) -> Option<Self::Item> {
self.peek()
}
}