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}