use crate::{Char, Error, Result, StreamPosition};
const BUFFER_SIZE : usize = 2048;
const BUFFER_SLACK : usize = 4;
pub struct Reader<R:std::io::Read> {
buf_reader : R,
eof_on_no_data : bool,
eof : bool,
current : [u8; BUFFER_SIZE],
start : usize,
end : usize,
valid_end : usize,
stream_pos : StreamPosition,
}
impl <R:std::io::Read> Reader<R> {
pub fn new(buf_reader: R) -> Self {
Self {
buf_reader,
eof_on_no_data : true,
eof : false,
current : [0; BUFFER_SIZE],
start : 0,
end : 0,
valid_end : 0,
stream_pos : StreamPosition::new(),
}
}
pub fn set_eof_on_no_data(mut self, eof_on_no_data:bool) -> Self {
self.eof_on_no_data = eof_on_no_data;
self
}
pub fn set_position(&mut self, stream_pos:StreamPosition) {
self.stream_pos = stream_pos;
}
pub fn set_eof(&mut self, eof:bool) {
self.eof = eof;
}
pub fn eof(&self) -> bool {
self.eof
}
pub fn complete(self) -> (R, StreamPosition, Vec<u8>) {
(self.buf_reader, self.stream_pos, self.current[self.start..self.end].into())
}
pub fn drop_buffer(&mut self) {
self.stream_pos.move_on_bytes(self.end - self.start);
self.start = self.end;
}
pub fn buffer_is_empty(&self) -> bool {
self.start == self.end
}
pub fn borrow_buffer(&self) -> &[u8] {
&self.current[self.start..self.end]
}
pub fn borrow_pos(&self) -> &StreamPosition {
&self.stream_pos
}
pub fn borrow(&self) -> &R {
&self.buf_reader
}
pub fn borrow_mut(&mut self) -> &mut R {
&mut self.buf_reader
}
fn fetch_input(&mut self) -> Result<usize> {
if self.start>BUFFER_SIZE-BUFFER_SLACK {
let n = self.end - self.start;
if n>0 {
for i in 0..n {
self.current[i] = self.current[self.start+i];
}
}
self.valid_end -= self.start;
self.start = 0; self.end = n; }
let n = self.buf_reader.read( &mut self.current[self.end..BUFFER_SIZE] )?;
self.end += n;
if n==0 && self.eof_on_no_data {
self.eof = true;
}
Ok(n)
}
pub fn next_char(&mut self) -> Result<Char> {
if self.eof {
Ok(Char::Eof)
} else if self.start == self.end { if self.fetch_input()? == 0 {
Ok(Char::NoData)
} else {
self.next_char()
}
} else if self.start < self.valid_end { let s = {
unsafe {
std::str::from_utf8_unchecked(&self.current[self.start..self.valid_end])
}
};
let ch = s.chars().next().unwrap();
let n = ch.len_utf8();
self.start += n;
self.stream_pos.move_by(n, ch);
Ok(Char::Char(ch))
} else { match std::str::from_utf8(&self.current[self.start..self.end]) {
Ok(_) => { self.valid_end = self.end;
self.next_char()
}
Err(e) => { if e.valid_up_to()>0 { self.valid_end = self.start+e.valid_up_to();
self.next_char()
} else { match e.error_len() {
None => { match self.fetch_input()? {
0 => { if self.eof {
Error::malformed_utf8(self.stream_pos, self.end-self.start)
} else {
Ok(Char::NoData)
}
}
_ => { self.next_char()
}
}
}
Some(n) => { let r = Error::malformed_utf8(self.stream_pos, n);
self.stream_pos.move_on_bytes(n);
self.start += n;
r
},
}
}
},
}
}
}
}
#[allow(missing_doc_code_examples)]
impl <'a, R:std::io::Read> Iterator for &'a mut Reader<R> {
type Item = Result<char>;
fn next(&mut self) -> Option<Self::Item> {
match self.next_char() {
Ok(Char::Char(ch)) => Some(Ok(ch)),
Ok(_) => None,
Err(x) => Some(Err(x)),
}
}
}