1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
|
use std::{
cmp::{max, min},
io::Cursor,
};
use crate::error::{ParsedError, ParsingError};
mod sync;
pub(crate) use sync::BufLoader;
const INIT_BUF_SIZE: usize = 4096;
const MIN_GROW_SIZE: usize = 2 * 4096;
const MAX_GROW_SIZE: usize = 10 * 4096;
pub(crate) trait BufLoad {
fn buf(&self) -> &[u8];
fn buf_mut(&mut self) -> &mut Vec<u8>;
fn into_vec(self) -> Vec<u8>;
#[allow(unused)]
fn cursor<Idx>(&self, idx: Idx) -> Cursor<&[u8]>
where
Idx: std::slice::SliceIndex<[u8], Output = [u8]>,
{
Cursor::new(&self.buf()[idx])
}
fn clear(&mut self) {
self.buf_mut().clear();
}
}
pub(crate) trait Load: BufLoad {
fn read_buf(&mut self, n: usize) -> std::io::Result<usize>;
fn skip(&mut self, n: usize) -> std::io::Result<()>;
fn load_and_parse<P, O>(&mut self, mut parse: P) -> Result<O, ParsedError>
where
P: FnMut(&[u8]) -> Result<O, ParsingError>,
{
self.load_and_parse_at(|x, _| parse(x), 0)
}
#[tracing::instrument(skip_all)]
fn load_and_parse_at<P, O>(&mut self, mut parse: P, at: usize) -> Result<O, ParsedError>
where
P: FnMut(&[u8], usize) -> Result<O, ParsingError>,
{
if at >= self.buf().len() {
self.read_buf(INIT_BUF_SIZE)?;
}
loop {
match parse(self.buf(), at) {
Ok(o) => return Ok(o),
Err(ParsingError::ClearAndSkip(n)) => {
tracing::debug!(n, "clear and skip bytes");
self.skip(n - self.buf().len())?;
self.clear();
self.read_buf(INIT_BUF_SIZE)?;
}
Err(ParsingError::Need(i)) => {
tracing::debug!(need = i, "need more bytes");
let to_read = max(i, MIN_GROW_SIZE);
let to_read = min(to_read, MAX_GROW_SIZE);
let n = self.read_buf(to_read)?;
if n == 0 {
return Err(ParsedError::NoEnoughBytes);
}
tracing::debug!(actual_read = n, "has been read");
}
Err(ParsingError::Failed(s)) => return Err(ParsedError::Failed(s)),
}
}
}
}
|