use std::io::{Error, ErrorKind, Read};
use crate::{
pcap::{PcapParseError, PcapReadError},
pcapng::errors::{PcapNgParseError, PcapNgReadError},
};
#[derive(Debug)]
pub(crate) struct ReadBuffer<R: Read> {
reader: R,
buffer: Vec<u8>,
pos: usize,
len: usize,
pub(crate) bytes_used: u64,
}
impl<R: Read> ReadBuffer<R> {
pub fn new(reader: R) -> Self {
Self::with_capacity(reader, 8_000_000)
}
pub fn with_capacity(reader: R, capacity: usize) -> Self {
Self {
reader,
buffer: vec![0_u8; capacity],
pos: 0,
len: 0,
bytes_used: 0,
}
}
pub fn parse_with<'a, 'b: 'a, 'c: 'a, F, O, E>(&'c mut self, mut parser: F) -> Result<O, E::ReadError>
where
F: FnMut(&'a [u8]) -> Result<(&'a [u8], O), E>,
F: 'b,
O: 'a,
E: ReadBufferParseError,
{
loop {
let buf = &self.buffer[self.pos..self.len];
let buf: &'a [u8] = unsafe { std::mem::transmute(buf) };
match parser(buf) {
Ok((rem, value)) => {
self.advance_with_slice(rem);
return Ok(value);
}
Err(e) if e.is_incomplete() => {
if buf.len() == self.buffer.len() {
return Err(E::from_io(Error::from(ErrorKind::UnexpectedEof)));
}
let nb_read = self.fill_buf().map_err(E::from_io)?;
if nb_read == 0 {
return Err(E::from_io(Error::from(ErrorKind::UnexpectedEof)));
}
}
Err(e) => return Err(e.into_read_error()),
}
}
}
fn fill_buf(&mut self) -> Result<usize, std::io::Error> {
let rem_len = unsafe {
let buf_ptr_mut = self.buffer.as_mut_ptr();
let rem_ptr_mut = buf_ptr_mut.add(self.pos);
std::ptr::copy(rem_ptr_mut, buf_ptr_mut, self.len - self.pos);
self.len - self.pos
};
let nb_read = self.reader.read(&mut self.buffer[rem_len..])?;
self.len = rem_len + nb_read;
self.pos = 0;
Ok(nb_read)
}
fn advance(&mut self, nb_bytes: usize) {
assert!(self.pos + nb_bytes <= self.len);
self.pos += nb_bytes;
self.bytes_used += nb_bytes as u64;
}
fn advance_with_slice(&mut self, rem: &[u8]) {
let diff_len = (rem.as_ptr() as usize)
.checked_sub(self.buffer().as_ptr() as usize)
.expect("Rem is not a sub slice of self.buffer");
self.advance(diff_len)
}
pub fn buffer(&self) -> &[u8] {
&self.buffer[self.pos..self.len]
}
pub fn has_data_left(&mut self) -> Result<bool, std::io::Error> {
if self.buffer().is_empty() {
let nb_read = self.fill_buf()?;
if nb_read == 0 {
return Ok(false);
}
}
Ok(true)
}
pub fn into_inner(self) -> R {
self.reader
}
pub fn get_ref(&self) -> &R {
&self.reader
}
}
pub(crate) trait ReadBufferParseError {
type ReadError;
fn is_incomplete(&self) -> bool;
fn from_io(error: Error) -> Self::ReadError;
fn into_read_error(self) -> Self::ReadError;
}
impl ReadBufferParseError for PcapParseError {
type ReadError = PcapReadError;
#[inline]
fn is_incomplete(&self) -> bool {
matches!(self, Self::IncompleteBuffer(_, _))
}
#[inline]
fn from_io(error: Error) -> Self::ReadError {
PcapReadError::Io(error)
}
#[inline]
fn into_read_error(self) -> Self::ReadError {
match self {
Self::IncompleteBuffer(_, _) => PcapReadError::Io(Error::from(ErrorKind::UnexpectedEof)),
Self::Validation(val) => PcapReadError::Validation(val),
}
}
}
impl ReadBufferParseError for PcapNgParseError {
type ReadError = PcapNgReadError;
#[inline]
fn is_incomplete(&self) -> bool {
matches!(self, Self::IncompleteBuffer(_, _))
}
#[inline]
fn from_io(error: Error) -> Self::ReadError {
PcapNgReadError::Io(error)
}
#[inline]
fn into_read_error(self) -> Self::ReadError {
self.into()
}
}
#[cfg(test)]
mod test {
}