pcap_file/pcap/parser.rs
1use byteorder_slice::{BigEndian, LittleEndian};
2
3use super::RawPcapPacket;
4use crate::errors::*;
5use crate::pcap::{PcapHeader, PcapPacket};
6use crate::Endianness;
7
8
9/// Parses a Pcap from a slice of bytes.
10///
11/// You can match on [`PcapError::IncompleteBuffer`](crate::errors::PcapError) to known if the parser need more data.
12///
13/// # Example
14/// ```no_run
15/// use pcap_file::pcap::PcapParser;
16/// use pcap_file::PcapError;
17///
18/// let pcap = vec![0_u8; 0];
19/// let mut src = &pcap[..];
20///
21/// // Creates a new parser and parse the pcap header
22/// let (rem, pcap_parser) = PcapParser::new(&pcap[..]).unwrap();
23/// src = rem;
24///
25/// loop {
26/// match pcap_parser.next_packet(src) {
27/// Ok((rem, packet)) => {
28/// // Do something
29///
30/// // Don't forget to update src
31/// src = rem;
32///
33/// // No more data, if no more incoming either then this is the end of the file
34/// if rem.is_empty() {
35/// break;
36/// }
37/// },
38/// Err(PcapError::IncompleteBuffer) => {}, // Load more data into src
39/// Err(_) => {}, // Parsing error
40/// }
41/// }
42/// ```
43#[derive(Debug)]
44pub struct PcapParser {
45 header: PcapHeader,
46}
47
48impl PcapParser {
49 /// Creates a new [`PcapParser`].
50 ///
51 /// Returns the remainder and the parser.
52 pub fn new(slice: &[u8]) -> PcapResult<(&[u8], PcapParser)> {
53 let (slice, header) = PcapHeader::from_slice(slice)?;
54
55 let parser = PcapParser { header };
56
57 Ok((slice, parser))
58 }
59
60 /// Returns the remainder and the next [`PcapPacket`].
61 pub fn next_packet<'a>(&self, slice: &'a [u8]) -> PcapResult<(&'a [u8], PcapPacket<'a>)> {
62 match self.header.endianness {
63 Endianness::Big => PcapPacket::from_slice::<BigEndian>(slice, self.header.ts_resolution, self.header.snaplen),
64 Endianness::Little => PcapPacket::from_slice::<LittleEndian>(slice, self.header.ts_resolution, self.header.snaplen),
65 }
66 }
67
68 /// Returns the remainder and the next [`RawPcapPacket`].
69 pub fn next_raw_packet<'a>(&self, slice: &'a [u8]) -> PcapResult<(&'a [u8], RawPcapPacket<'a>)> {
70 match self.header.endianness {
71 Endianness::Big => RawPcapPacket::from_slice::<BigEndian>(slice),
72 Endianness::Little => RawPcapPacket::from_slice::<LittleEndian>(slice),
73 }
74 }
75
76 /// Returns the header of the pcap file.
77 pub fn header(&self) -> PcapHeader {
78 self.header
79 }
80}