pcap_file/read_buffer.rs
1use std::io::{Error, ErrorKind, Read};
2
3use crate::PcapError;
4
5
6/// Internal structure that bufferize its input and allow to parse element from its buffer.
7#[derive(Debug)]
8pub(crate) struct ReadBuffer<R: Read> {
9 /// Reader from which we read the data from
10 reader: R,
11 /// Internal buffer
12 buffer: Vec<u8>,
13 /// Current start position of the buffer
14 pos: usize,
15 /// Current end position of the buffer
16 len: usize,
17}
18
19impl<R: Read> ReadBuffer<R> {
20 /// Creates a new ReadBuffer with capacity of 8_000_000
21 pub fn new(reader: R) -> Self {
22 Self::with_capacity(reader, 8_000_000)
23 }
24
25 /// Creates a new ReadBuffer with the given capacity
26 pub fn with_capacity(reader: R, capacity: usize) -> Self {
27 Self { reader, buffer: vec![0_u8; capacity], pos: 0, len: 0 }
28 }
29
30 /// Parse data from the internal buffer
31 ///
32 /// Safety
33 ///
34 /// The parser must NOT keep a reference to the buffer in input.
35 pub fn parse_with<'a, 'b: 'a, 'c: 'a, F, O>(&'c mut self, mut parser: F) -> Result<O, PcapError>
36 where
37 F: FnMut(&'a [u8]) -> Result<(&'a [u8], O), PcapError>,
38 F: 'b,
39 O: 'a,
40 {
41 loop {
42 let buf = &self.buffer[self.pos..self.len];
43
44 // Sound because 'b and 'c must outlive 'a so the buffer cannot be modified while someone has a ref on it
45 let buf: &'a [u8] = unsafe { std::mem::transmute(buf) };
46
47 match parser(buf) {
48 Ok((rem, value)) => {
49 self.advance_with_slice(rem);
50 return Ok(value);
51 },
52
53 Err(PcapError::IncompleteBuffer) => {
54 // The parsed data len should never be more than the buffer capacity
55 if buf.len() == self.buffer.len() {
56 return Err(PcapError::IoError(Error::from(ErrorKind::UnexpectedEof)));
57 }
58
59 let nb_read = self.fill_buf().map_err(PcapError::IoError)?;
60 if nb_read == 0 {
61 return Err(PcapError::IoError(Error::from(ErrorKind::UnexpectedEof)));
62 }
63 },
64
65 Err(e) => return Err(e),
66 }
67 }
68 }
69
70 /// Fill the inner buffer.
71 /// Copy the remaining data inside buffer at its start and the fill the end part with data from the reader.
72 fn fill_buf(&mut self) -> Result<usize, std::io::Error> {
73 // Copy the remaining data to the start of the buffer
74 let rem_len = unsafe {
75 let buf_ptr_mut = self.buffer.as_mut_ptr();
76 let rem_ptr_mut = buf_ptr_mut.add(self.pos);
77 std::ptr::copy(rem_ptr_mut, buf_ptr_mut, self.len - self.pos);
78 self.len - self.pos
79 };
80
81 let nb_read = self.reader.read(&mut self.buffer[rem_len..])?;
82
83 self.len = rem_len + nb_read;
84 self.pos = 0;
85
86 Ok(nb_read)
87 }
88
89 /// Advance the internal buffer position.
90 fn advance(&mut self, nb_bytes: usize) {
91 assert!(self.pos + nb_bytes <= self.len);
92 self.pos += nb_bytes;
93 }
94
95 /// Advance the internal buffer position.
96 fn advance_with_slice(&mut self, rem: &[u8]) {
97 // Compute the length between the buffer and the slice
98 let diff_len = (rem.as_ptr() as usize)
99 .checked_sub(self.buffer().as_ptr() as usize)
100 .expect("Rem is not a sub slice of self.buffer");
101
102 self.advance(diff_len)
103 }
104
105 /// Return the valid data of the internal buffer
106 pub fn buffer(&self) -> &[u8] {
107 &self.buffer[self.pos..self.len]
108 }
109
110 /// Return true there are some data that can be read
111 pub fn has_data_left(&mut self) -> Result<bool, std::io::Error> {
112 // The buffer can be empty and the reader can still have data
113 if self.buffer().is_empty() {
114 let nb_read = self.fill_buf()?;
115 if nb_read == 0 {
116 return Ok(false);
117 }
118 }
119
120 Ok(true)
121 }
122
123 /// Return the inner reader
124 pub fn into_inner(self) -> R {
125 self.reader
126 }
127
128 /// Return a reference over the inner reader
129 pub fn get_ref(&self) -> &R {
130 &self.reader
131 }
132}
133
134#[cfg(test)]
135mod test {
136 /*
137 // Shouldn't compile
138 #[test]
139 fn parse_with_safety() {
140 let a = &[0_u8; 10];
141 let b = &mut &a[..];
142
143 let input = vec![1_u8; 100];
144 let input_read = &mut &input[..];
145 let mut reader = super::ReadBuffer::new(input_read);
146
147 unsafe {
148 reader.parse_with(|buf| {
149 *b = buf;
150 Ok((buf, ()))
151 });
152 }
153
154 unsafe {
155 reader.has_data_left();
156 }
157
158 println!("{:?}", b);
159 }
160 */
161}