pcap_file/pcapng/
reader.rs

1use std::io::Read;
2
3use super::blocks::block_common::{Block, RawBlock};
4use super::blocks::enhanced_packet::EnhancedPacketBlock;
5use super::blocks::interface_description::InterfaceDescriptionBlock;
6use super::blocks::section_header::SectionHeaderBlock;
7use super::PcapNgParser;
8use crate::errors::PcapError;
9use crate::read_buffer::ReadBuffer;
10
11
12/// Reads a PcapNg from a reader.
13///
14/// # Example
15/// ```rust,no_run
16/// use std::fs::File;
17///
18/// use pcap_file::pcapng::PcapNgReader;
19///
20/// let file_in = File::open("test.pcapng").expect("Error opening file");
21/// let mut pcapng_reader = PcapNgReader::new(file_in).unwrap();
22///
23/// // Read test.pcapng
24/// while let Some(block) = pcapng_reader.next_block() {
25///     //Check if there is no error
26///     let block = block.unwrap();
27///
28///     //Do something
29/// }
30/// ```
31pub struct PcapNgReader<R: Read> {
32    parser: PcapNgParser,
33    reader: ReadBuffer<R>,
34}
35
36impl<R: Read> PcapNgReader<R> {
37    /// Creates a new [`PcapNgReader`] from a reader.
38    ///
39    /// Parses the first block which must be a valid SectionHeaderBlock.
40    pub fn new(reader: R) -> Result<PcapNgReader<R>, PcapError> {
41        let mut reader = ReadBuffer::new(reader);
42        let parser = reader.parse_with(PcapNgParser::new)?;
43        Ok(Self { parser, reader })
44    }
45
46    /// Returns the next [`Block`].
47    pub fn next_block(&mut self) -> Option<Result<Block, PcapError>> {
48        match self.reader.has_data_left() {
49            Ok(has_data) => {
50                if has_data {
51                    Some(self.reader.parse_with(|src| self.parser.next_block(src)))
52                }
53                else {
54                    None
55                }
56            },
57            Err(e) => Some(Err(PcapError::IoError(e))),
58        }
59    }
60
61    /// Returns the next [`RawBlock`].
62    pub fn next_raw_block(&mut self) -> Option<Result<RawBlock, PcapError>> {
63        match self.reader.has_data_left() {
64            Ok(has_data) => {
65                if has_data {
66                    Some(self.reader.parse_with(|src| self.parser.next_raw_block(src)))
67                }
68                else {
69                    None
70                }
71            },
72            Err(e) => Some(Err(PcapError::IoError(e))),
73        }
74    }
75
76    /// Returns the current [`SectionHeaderBlock`].
77    pub fn section(&self) -> &SectionHeaderBlock<'static> {
78        self.parser.section()
79    }
80
81    /// Returns all the current [`InterfaceDescriptionBlock`].
82    pub fn interfaces(&self) -> &[InterfaceDescriptionBlock<'static>] {
83        self.parser.interfaces()
84    }
85
86    /// Returns the [`InterfaceDescriptionBlock`] corresponding to the given packet
87    pub fn packet_interface(&self, packet: &EnhancedPacketBlock) -> Option<&InterfaceDescriptionBlock> {
88        self.interfaces().get(packet.interface_id as usize)
89    }
90
91    /// Consumes the [`Self`], returning the wrapped reader.
92    pub fn into_inner(self) -> R {
93        self.reader.into_inner()
94    }
95
96    /// Gets a reference to the wrapped reader.
97    pub fn get_ref(&self) -> &R {
98        self.reader.get_ref()
99    }
100}