use std::ffi::OsStr;
use crate::TextReader;
#[derive(Debug)]
pub struct Detector<'a> {
reader: &'a mut TextReader,
compares: Vec<char>,
last_len: usize,
}
impl<'a> Detector<'a> {
pub fn new(reader: &'a mut TextReader) -> Self {
Self { reader, compares: Vec::new(), last_len: 0 }
}
pub fn next_char(&mut self, ch: char) -> &mut Self {
self.compares.push(ch);
self
}
pub fn next_text<S: AsRef<OsStr>>(&mut self, text: S) -> &mut Self {
text.as_ref().to_str().unwrap().chars().collect::<Vec<char>>()
.iter()
.for_each(|ch| { self.next_char(ch.clone()); });
self
}
pub fn yes(&mut self) -> bool {
self.detect()
}
pub fn no(&mut self) -> bool {
!self.detect()
}
pub fn rollback(&mut self) -> &mut Self {
for _ in 0..self.last_len {
self.reader.back();
}
self
}
fn detect(&mut self) -> bool {
let mut ix = 0;
let len = self.compares.len();
while self.reader.has_next() {
match self.reader.next() {
Some(ch) => {
let compare = match self.compares.get(ix) {
Some(c) => c.clone(),
None => {
self.reader.back();
self.last_len = len;
return true;
}
};
if ch != compare {
self.restore(ix + 1);
return false;
}
ix += 1;
}
None => {
self.restore(ix);
return false;
}
}
}
let same = ix == len;
if !same {
self.restore(ix);
} else {
self.last_len = len;
}
same
}
fn restore(&mut self, count: usize) -> &mut Self {
if count == 0 {
return self;
}
for _ in 0..count {
self.reader.back();
}
self
}
}