pcap_rs/
iter.rs

1//! A nice and simple iterator over the file.
2use crate::{parse_header, parse_record, Header, Record};
3use nom::{error::ErrorKind, number::Endianness, Err};
4use std::io::BufRead;
5
6/// Represents an entry in the file.
7#[derive(PartialEq, Debug)]
8pub enum Block {
9    /// Header of the file.
10    ///
11    /// This type of entry occurs only once at the beginning of each file.
12    Header(Header),
13    /// Packet record.
14    ///
15    /// This type of entry occurs until the end of the file is reached.
16    Record(Record),
17
18    /// Parsing error.
19    Error(ErrorKind),
20}
21
22/// Iterates over a BufRead.
23pub struct PcapIterator<T: BufRead> {
24    first_block: bool,
25    reader: T,
26    endianness: Endianness,
27    nano_sec: bool,
28}
29impl<T: BufRead> PcapIterator<T> {
30    pub fn new(stream: T) -> PcapIterator<T> {
31        PcapIterator {
32            first_block: true,
33            reader: stream,
34            endianness: Endianness::Big,
35            nano_sec: false,
36        }
37    }
38}
39
40impl<T: BufRead> Iterator for PcapIterator<T> {
41    type Item = Block;
42    fn next(&mut self) -> Option<Block> {
43        // these are required to avoid borrowing self inside the first closure while it is still
44        // mutable borrowed by `self.read.fill_buf()`.
45        let first_block = self.first_block;
46        let endianness = self.endianness;
47        let nano_sec = self.nano_sec;
48
49        self.reader
50            .fill_buf()
51            .and_then(|b| {
52                (if first_block {
53                    parse_header(b)
54                        .and_then(|(u, h)| Ok(Some((b.len() - u.len(), Block::Header(h)))))
55                } else {
56                    parse_record(b, endianness, nano_sec)
57                        .and_then(|(u, r)| Ok(Some((b.len() - u.len(), Block::Record(r)))))
58                })
59                .or_else(|e| match e {
60                    Err::Incomplete(_)
61                    | Err::Error((_, ErrorKind::Complete))
62                    | Err::Failure((_, ErrorKind::Complete)) => Ok(None),
63                    Err::Error((_, e)) | Err::Failure((_, e)) => Ok(Some((0, Block::Error(e)))),
64                })
65            })
66            .unwrap_or(None)
67            .and_then(|(c, block)| {
68                self.first_block = false;
69                if c != 0 {
70                    self.reader.consume(c);
71                }
72                if let Block::Header(ref h) = block {
73                    self.endianness = h.endianness;
74                    self.nano_sec = h.nano_sec;
75                }
76                Some(block)
77            })
78    }
79}