use std::io::BufRead;
use crate::language::text::{ buffer::Buffer, location::Location };
pub struct ReadBuffer<'a, R: BufRead>
{
reader: &'a mut R,
location: Location,
tab_width: usize,
current_char: Option<char>
}
impl<'a, R: BufRead> ReadBuffer<'a, R>
{
pub fn new(origin: &str, reader: &'a mut R, tab_width: Option<usize>) -> Self
{
Self
{
reader,
location: Location::new(origin, 1, 1),
tab_width: tab_width.unwrap_or(4),
current_char: None
}
}
fn read_char(&mut self) -> Option<char>
{
let mut buffer = [0; 4];
for length in 1..=buffer.len()
{
self.reader.read_exact(&mut buffer[length - 1..length]).ok()?;
match std::str::from_utf8(&buffer[..length])
{
Ok(text) => return text.chars().next(),
Err(error) if error.error_len().is_none() => continue,
Err(_) => return None
}
}
None
}
}
impl<'a, R: BufRead> Buffer for ReadBuffer<'a, R>
{
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.read_char();
self.current_char = next;
next
}
}
}
fn next(&mut self) -> Option<char>
{
let next = self.current_char.take().or_else(|| self.read_char());
if let Some(next) = next
{
self.increment_location(next, self.tab_width);
}
next
}
}