use std::str::Chars;
use super::location::Location;
pub trait Buffer
{
fn location(&self) -> &Location;
fn location_mut(&mut self) -> &mut Location;
fn peek_next(&mut self) -> Option<char>;
fn next(&mut self) -> Option<char>;
fn increment_location(&mut self, next: char, tab_width: usize)
{
let location = &mut self.location_mut();
match next
{
'\t' =>
{
let mut column = location.column;
column += tab_width - ((column - 1) % tab_width);
location.column = column;
}
'\n' =>
{
location.line += 1;
location.column = 1;
},
_ => location.column += 1
}
}
}
pub struct SimpleBuffer<'a>
{
text: Chars<'a>,
location: Location,
tab_width: usize,
current_char: Option<char>
}
impl<'a> SimpleBuffer<'a>
{
pub fn new(origin: &str, source: &'a str, tab_width: Option<usize>) -> Self
{
Self
{
text: source.chars(),
location: Location::new(origin, 1, 1),
tab_width: tab_width.unwrap_or(4),
current_char: None
}
}
}
impl<'a> Buffer for SimpleBuffer<'a>
{
fn location(&self) -> &Location
{
&self.location
}
fn location_mut(&mut self) -> &mut Location
{
&mut self.location
}
fn peek_next(&mut self) -> Option<char>
{
match self.current_char
{
Some(_) => self.current_char,
None =>
{
let next = self.text.next();
self.current_char = next;
next
}
}
}
fn next(&mut self) -> Option<char>
{
let next = self.current_char.take().or_else(|| self.text.next());
if let Some(next) = next
{
self.increment_location(next, self.tab_width);
}
next
}
}