use crate::blocks::{PcapBlock, PcapBlockOwned};
use crate::error::PcapError;
use crate::pcapng::*;
use nom::combinator::{complete, map};
use nom::multi::many1;
use nom::{IResult, Needed, Parser as _};
use std::fmt;
#[derive(Default)]
pub(crate) struct CurrentSectionInfo {
pub(crate) big_endian: bool,
}
pub struct PcapNGSlice<'a> {
info: CurrentSectionInfo,
rem: &'a [u8],
}
impl PcapNGSlice<'_> {
pub fn from_slice(i: &[u8]) -> Result<PcapNGSlice<'_>, nom::Err<PcapError<&[u8]>>> {
let (_rem, _shb) = parse_sectionheaderblock(i)?;
let info = CurrentSectionInfo::default();
let rem = i;
Ok(PcapNGSlice { info, rem })
}
}
impl<'a> Iterator for PcapNGSlice<'a> {
type Item = Result<PcapBlockOwned<'a>, nom::Err<PcapError<&'a [u8]>>>;
fn next(&mut self) -> Option<Self::Item> {
if self.rem.is_empty() {
return None;
}
let parse = if self.info.big_endian {
parse_block_be
} else {
parse_block_le
};
let r = parse(self.rem).map(|(rem, b)| {
self.rem = rem;
if let Block::SectionHeader(ref shb) = b {
self.info.big_endian = shb.big_endian();
}
PcapBlockOwned::from(b)
});
Some(r)
}
}
pub struct PcapNGCapture<'a> {
pub sections: Vec<Section<'a>>,
}
impl fmt::Debug for PcapNGCapture<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
writeln!(f, "PcapNGCapture:")
}
}
pub struct PcapNGCaptureIterator<'a> {
cap: &'a PcapNGCapture<'a>,
idx: usize,
}
impl<'a> Iterator for PcapNGCaptureIterator<'a> {
type Item = PcapBlock<'a>;
fn next(&mut self) -> Option<PcapBlock<'a>> {
if self.cap.sections.len() != 1 {
unimplemented!();
}
self.cap.sections[0].blocks.get(self.idx).map(|b| {
self.idx += 1;
PcapBlock::from(b)
})
}
}
impl<'a> PcapNGCapture<'a> {
pub fn from_file(i: &[u8]) -> Result<PcapNGCapture<'_>, PcapError<&[u8]>> {
match parse_pcapng(i) {
Ok((_, pcap)) => Ok(pcap),
Err(nom::Err::Error(e)) | Err(nom::Err::Failure(e)) => Err(e),
Err(nom::Err::Incomplete(Needed::Size(n))) => Err(PcapError::Incomplete(n.into())),
Err(nom::Err::Incomplete(Needed::Unknown)) => Err(PcapError::Incomplete(0)),
}
}
pub fn iter(&'a self) -> PcapNGCaptureIterator<'a> {
PcapNGCaptureIterator { cap: self, idx: 0 }
}
}
pub fn parse_pcapng(i: &[u8]) -> IResult<&[u8], PcapNGCapture<'_>, PcapError<&[u8]>> {
map(many1(complete(parse_section)), |sections| PcapNGCapture {
sections,
})
.parse(i)
}