use std::io::Read;
use super::{PcapParser, RawPcapPacket};
use crate::pcap::{PcapHeader, PcapPacket, PcapReadError};
use crate::read_buffer::ReadBuffer;
#[derive(Debug)]
pub struct PcapReader<R: Read> {
parser: PcapParser,
reader: ReadBuffer<R>,
}
impl<R: Read> PcapReader<R> {
pub fn new(reader: R) -> Result<PcapReader<R>, PcapReadError> {
let mut reader = ReadBuffer::new(reader);
let parser = reader.parse_with(PcapParser::new)?;
Ok(PcapReader { parser, reader })
}
pub fn with_capacity(reader: R, capacity: usize) -> Result<PcapReader<R>, PcapReadError> {
let mut reader = ReadBuffer::with_capacity(reader, capacity);
let parser = reader.parse_with(PcapParser::new)?;
Ok(PcapReader { parser, reader })
}
pub fn into_inner(self) -> R {
self.reader.into_inner()
}
pub fn next_packet(&mut self) -> Option<Result<PcapPacket<'_>, PcapReadError>> {
match self.reader.has_data_left() {
Ok(has_data) => {
if has_data {
Some(self.reader.parse_with(|src| self.parser.next_packet(src)))
} else {
None
}
}
Err(e) => Some(Err(PcapReadError::Io(e))),
}
}
pub fn next_raw_packet(&mut self) -> Option<Result<RawPcapPacket<'_>, PcapReadError>> {
match self.reader.has_data_left() {
Ok(has_data) => {
if has_data {
Some(self.reader.parse_with(|src| self.parser.next_raw_packet(src)))
} else {
None
}
}
Err(e) => Some(Err(PcapReadError::Io(e))),
}
}
pub fn header(&self) -> PcapHeader {
self.parser.header()
}
}
impl<R: Read> IntoIterator for PcapReader<R> {
type Item = Result<PcapPacket<'static>, PcapReadError>;
type IntoIter = PcapReaderIterator<R>;
fn into_iter(self) -> Self::IntoIter {
PcapReaderIterator {
reader: self,
err: false,
}
}
}
#[derive(Debug)]
pub struct PcapReaderIterator<R: Read> {
reader: PcapReader<R>,
err: bool,
}
impl<R: Read> PcapReaderIterator<R> {
pub fn get_ref(&self) -> &PcapReader<R> {
&self.reader
}
pub fn into_inner(self) -> PcapReader<R> {
self.reader
}
}
impl<R: Read> Iterator for PcapReaderIterator<R> {
type Item = Result<PcapPacket<'static>, PcapReadError>;
fn next(&mut self) -> Option<Self::Item> {
if self.err {
return None;
}
let packet = self
.reader
.next_packet()
.map(|packet| packet.map(PcapPacket::into_owned));
if matches!(packet, Some(Err(_))) {
self.err = true;
}
packet
}
}