pub trait Reader<T>: Iterator {
fn len(&self) -> usize;
fn pos(&self) -> usize;
fn rollback(&mut self, amount: usize) -> Result<(), ()>;
fn is_end(&self) -> bool {
self.len() == 0 || self.len() <= self.pos()
}
fn try_read(&mut self, amount: usize) -> Option<T>;
}
pub struct TextReader {
pos: usize,
text: Vec<char>,
}
impl Iterator for TextReader {
type Item = char;
fn next(&mut self) -> Option<Self::Item> {
let current = self.text.get(self.pos).copied();
self.pos += 1;
current
}
}
impl Reader<String> for TextReader {
fn len(&self) -> usize {
self.text.len()
}
fn pos(&self) -> usize {
self.pos
}
fn rollback(&mut self, amount: usize) -> Result<(), ()> {
if self.pos < amount {
return Err(());
}
self.pos -= amount;
Ok(())
}
fn try_read(&mut self, amount: usize) -> Option<String> {
let mut s = String::with_capacity(amount);
let mut left = amount;
while left > 0 {
if self.is_end() {
self.pos -= amount - left;
return None;
}
let ch = self.next().unwrap();
s.push(ch);
left -= 1;
}
Some(s)
}
}
impl TextReader {
pub fn new() -> Self {
TextReader { pos: 0, text: vec![] }
}
pub fn from_text(s: &str) -> Self {
TextReader { pos: 0, text: s.chars().collect() }
}
pub fn read_until_char(&mut self, ch: char) -> Option<String> {
let mut s = String::new();
while self.is_end() == false {
let read_ch = self.next().unwrap();
s.push(read_ch);
if read_ch == ch {
return Some(s);
}
}
self.rollback(s.len()).unwrap();
None
}
}