hawktracer_parser/
data_provider.rs

1pub struct DataProvider {
2    reader: Box<dyn std::io::Read>,
3    buffer: [u8; 512],
4    data_pointer: usize,
5    data_available: usize,
6}
7
8#[derive(Debug)]
9pub enum DataError {
10    EndOfStream,
11    Utf8Error,
12    IOError(std::io::Error),
13}
14
15impl PartialEq for DataError {
16    fn eq(&self, other: &DataError) -> bool {
17        match (self, other) {
18            (DataError::IOError(_e1), DataError::IOError(_e2)) => true, // Assume error is the same if the type matches
19            (DataError::EndOfStream, DataError::EndOfStream) => true,
20            (DataError::Utf8Error, DataError::Utf8Error) => true,
21            _ => false,
22        }
23    }
24}
25
26impl DataProvider {
27    pub fn new(reader: Box<dyn std::io::Read>) -> DataProvider {
28        DataProvider {
29            reader,
30            buffer: [0; 512],
31            data_pointer: 0,
32            data_available: 0,
33        }
34    }
35
36    fn get_next_byte(&mut self) -> Result<u8, DataError> {
37        if self.data_pointer == self.data_available {
38            match self.load_data() {
39                Err(err) => return Err(DataError::IOError(err)),
40                Ok(_) => {
41                    if self.data_available == 0 {
42                        return Err(DataError::EndOfStream);
43                    }
44                }
45            }
46        }
47
48        let data = Ok(self.buffer[self.data_pointer]);
49        self.data_pointer += 1;
50        data
51    }
52
53    pub fn read_bytes(&mut self, buffer: &mut [u8]) -> Result<(), DataError> {
54        // TODO do it more efficiently by copying a whole slice
55        for b in buffer {
56            *b = match self.get_next_byte() {
57                Ok(value) => value,
58                Err(err) => return Err(err),
59            }
60        }
61
62        Ok(())
63    }
64
65    pub fn read_string(&mut self) -> Result<String, DataError> {
66        let mut data = std::vec::Vec::new();
67        loop {
68            match self.get_next_byte() {
69                Ok(0) => break,
70                Ok(b) => data.push(b),
71                Err(err) => return Err(err),
72            };
73        }
74
75        match String::from_utf8(data) {
76            Ok(res) => Ok(res),
77            Err(_err) => Err(DataError::Utf8Error),
78        }
79    }
80
81    fn load_data(&mut self) -> std::io::Result<usize> {
82        self.data_pointer = 0;
83        match self.reader.read(&mut self.buffer) {
84            Ok(size) => {
85                self.data_available = size;
86                Ok(size)
87            }
88            Err(err) => Err(err),
89        }
90    }
91}
92
93#[cfg(test)]
94pub mod tests {
95    use super::*;
96    use hawktracer_parser_test_utilities::FakeDataReader;
97
98    fn buffers_equal(b1: &[u8], b2: &[u8]) -> usize {
99        return b1.iter().zip(b2).map(|(a, b)| assert_eq!(a, b)).count();
100    }
101
102    #[test]
103    fn should_not_set_eos_if_still_have_data() {
104        let mut provider = DataProvider::new(Box::new(FakeDataReader::new(vec![1, 2], false)));
105        let mut buf = [0u8; 2];
106        assert!(provider.read_bytes(&mut buf).is_ok());
107
108        buffers_equal(&buf, &[1, 2]);
109    }
110
111    #[test]
112    fn should_set_eos_if_try_to_read_too_much_data() {
113        let mut provider =
114            DataProvider::new(Box::new(FakeDataReader::new(vec![1, 2, 3, 4], false)));
115        let mut buf = [0u8; 5];
116        assert!(provider.read_bytes(&mut buf).is_err());
117
118        buffers_equal(&buf[0..4], &[1, 2, 3, 4]);
119    }
120
121    #[test]
122    fn should_fail_if_data_reader_fails() {
123        let mut provider = DataProvider::new(Box::new(FakeDataReader::new(vec![1, 2], true)));
124        let mut buf = [0u8; 2];
125
126        assert!(provider.read_bytes(&mut buf).is_err());
127    }
128
129    #[test]
130    fn read_string_should_not_fail_if_valid_string() {
131        let mut provider = DataProvider::new(Box::new(FakeDataReader::new(vec![65, 66, 0], false)));
132
133        let message = provider.read_string();
134        assert!(message.is_ok());
135        assert_eq!("AB", message.unwrap());
136    }
137
138    #[test]
139    fn read_string_should_fail_if_no_zero_at_the_end() {
140        let mut provider =
141            DataProvider::new(Box::new(FakeDataReader::new(vec![65, 66, 67, 68], false)));
142
143        let message = provider.read_string();
144        assert!(message.is_err());
145    }
146
147    #[test]
148    fn read_string_should_fail_if_non_utf8_string() {
149        let mut provider =
150            DataProvider::new(Box::new(FakeDataReader::new(vec![65, 220, 0, 5], false)));
151
152        let message = provider.read_string();
153        assert!(message.is_err());
154    }
155}