se_io/
binary_reader.rs

1use std::{
2    fs::File,
3    io::{BufReader, Cursor, Error, ErrorKind},
4};
5
6use super::serialization::*;
7
8/// Binary data reader
9#[derive(Debug)]
10pub struct BinaryReader {
11    is_file: bool,
12    size: u64,
13    position: i64,
14    inner: super::DataInterface,
15}
16
17impl BinaryReader {
18    /// Create a `BinaryReader` from a file path.
19    pub fn from_path(path: &str) -> Result<Self, Error> {
20        let file = File::open(path)?;
21        let size = file.metadata()?.len();
22        let inner = super::DataInterface::File(BufReader::new(file));
23
24        Ok(Self {
25            is_file: true,
26            size,
27            position: 0,
28            inner,
29        })
30    }
31    /// Create a `BinaryReader` from a `File`.
32    pub fn from_file(file: File) -> Result<Self, Error> {
33        let size = file.metadata()?.len();
34        let inner = super::DataInterface::File(BufReader::new(file));
35
36        Ok(Self {
37            is_file: true,
38            size,
39            position: 0,
40            inner,
41        })
42    }
43    /// Create a `BinaryReader` from a `u8` slice.
44    pub fn from_bytes(bytes: &[u8]) -> Self {
45        let size = bytes.len() as u64;
46        let inner = super::DataInterface::Bytes(Cursor::new(bytes.to_vec()));
47
48        Self {
49            is_file: true,
50            size,
51            position: 0,
52            inner,
53        }
54    }
55    /// Read a specified number of bytes.
56    pub fn read(&mut self, len: u64) -> Result<Vec<u8>, Error> {
57        match self.inner.read(len) {
58            Ok(b) => {
59                self.position += len as i64;
60                Ok(b)
61            }
62            Err(e) => Err(e),
63        }
64    }
65    /// Seek to a specified position in the data.
66    pub fn seek(&mut self, pos: u64) -> Result<(), Error> {
67        match self.inner.seek(pos) {
68            Ok(()) => {
69                self.position = pos as i64;
70                Ok(())
71            }
72            Err(e) => Err(e),
73        }
74    }
75    /// Seek a specified amount of bytes in the data.
76    pub fn seek_relative(&mut self, offset: i64) -> Result<(), Error> {
77        match self.inner.seek_relative(offset) {
78            Ok(()) => {
79                self.position += offset;
80                Ok(())
81            }
82            Err(e) => Err(e),
83        }
84    }
85
86    /// Return the current position in the data.
87    pub fn pos(&self) -> u64 {
88        self.position as u64
89    }
90    /// Returns `true` if the reader is reading from a real file and `false` if it is reading from a buffer in memory.
91    pub fn is_file(&self) -> bool {
92        self.is_file
93    }
94    /// Returns size of the data.
95    pub fn size(&self) -> u64 {
96        self.size
97    }
98
99    /// Read a `u8` from the data.
100    pub fn read_u8(&mut self) -> Result<u8, Error> {
101        Ok(self.read(1)?[0])
102    }
103    /// Read a `u16` from the data. (Little Endian)
104    pub fn read_u16(&mut self) -> Result<u16, Error> {
105        Ok(read_u16(&self.read(2)?))
106    }
107    /// Read a `u32` from the data. (Little Endian)
108    pub fn read_u32(&mut self) -> Result<u32, Error> {
109        Ok(read_u32(&self.read(4)?))
110    }
111    /// Read a `u64` from the data. (Little Endian)
112    pub fn read_u64(&mut self) -> Result<u64, Error> {
113        Ok(read_u64(&self.read(8)?))
114    }
115    /// Read a `u128` from the data. (Little Endian)
116    pub fn read_u128(&mut self) -> Result<u128, Error> {
117        Ok(read_u128(&self.read(16)?))
118    }
119
120    /// Read a `i16` from the data. (Little Endian)
121    pub fn read_i16(&mut self) -> Result<i16, Error> {
122        Ok(read_i16(&self.read(2)?))
123    }
124    /// Read a `i32` from the data. (Little Endian)
125    pub fn read_i32(&mut self) -> Result<i32, Error> {
126        Ok(read_i32(&self.read(4)?))
127    }
128    /// Read a `i64` from the data. (Little Endian)
129    pub fn read_i64(&mut self) -> Result<i64, Error> {
130        Ok(read_i64(&self.read(8)?))
131    }
132    /// Read a `i128` from the data. (Little Endian)
133    pub fn read_i128(&mut self) -> Result<i128, Error> {
134        Ok(read_i128(&self.read(16)?))
135    }
136
137    /// Read a `f32` from the data. (Little Endian)
138    pub fn read_f32(&mut self) -> Result<f32, Error> {
139        Ok(read_f32(&self.read(4)?))
140    }
141    /// Read a `f64` from the data. (Little Endian)
142    pub fn read_f64(&mut self) -> Result<f64, Error> {
143        Ok(read_f64(&self.read(8)?))
144    }
145
146    /// Read a `u16` from the data. (Big Endian)
147    pub fn read_u16_be(&mut self) -> Result<u16, Error> {
148        Ok(read_u16_be(&self.read(2)?))
149    }
150    /// Read a `u32` from the data. (Big Endian)
151    pub fn read_u32_be(&mut self) -> Result<u32, Error> {
152        Ok(read_u32_be(&self.read(4)?))
153    }
154    /// Read a `u64` from the data. (Big Endian)
155    pub fn read_u64_be(&mut self) -> Result<u64, Error> {
156        Ok(read_u64_be(&self.read(8)?))
157    }
158    /// Read a `u128` from the data. (Big Endian)
159    pub fn read_u128_be(&mut self) -> Result<u128, Error> {
160        Ok(read_u128_be(&self.read(16)?))
161    }
162
163    /// Read a `i16` from the data. (Big Endian)
164    pub fn read_i16_be(&mut self) -> Result<i16, Error> {
165        Ok(read_i16_be(&self.read(2)?))
166    }
167    /// Read a `i32` from the data. (Big Endian)
168    pub fn read_i32_be(&mut self) -> Result<i32, Error> {
169        Ok(read_i32_be(&self.read(4)?))
170    }
171    /// Read a `i64` from the data. (Big Endian)
172    pub fn read_i64_be(&mut self) -> Result<i64, Error> {
173        Ok(read_i64_be(&self.read(8)?))
174    }
175    /// Read a `i128` from the data. (Big Endian)
176    pub fn read_i128_be(&mut self) -> Result<i128, Error> {
177        Ok(read_i128_be(&self.read(16)?))
178    }
179
180    /// Read a `f32` from the data. (Big Endian)
181    pub fn read_f32_be(&mut self) -> Result<f32, Error> {
182        Ok(read_f32_be(&self.read(4)?))
183    }
184    /// Read a `f64` from the data. (Big Endian)
185    pub fn read_f64_be(&mut self) -> Result<f64, Error> {
186        Ok(read_f64_be(&self.read(8)?))
187    }
188
189    /// Read a string of a specified length from the data. Fails if it encounters a non-ascii character.
190    pub fn read_string_ascii_limited(&mut self, len: u64) -> Result<String, Error> {
191        let buf = self.read(len)?;
192        let mut out = String::new();
193        for c in buf {
194            if c.is_ascii() {
195                out.push(c as char);
196            } else {
197                self.seek_relative(-(len as i64))?;
198                return Err(Error::new(
199                    ErrorKind::InvalidData,
200                    "Found non-ascii character while reading string",
201                ));
202            }
203        }
204        Ok(out)
205    }
206
207    /// Read a string from the data until it encounters a NUL(0x00)/non-ascii character or the end of the file. Doesn't fail.
208    pub fn read_string_ascii(&mut self) -> String {
209        let mut out = String::new();
210        let mut read = true;
211        while read {
212            let c = self.read_u8();
213            match c {
214                Ok(c) => {
215                    if c.is_ascii() && c != 0x00 {
216                        out.push(c as char);
217                    } else {
218                        read = false;
219                    }
220                }
221                Err(_) => read = false,
222            }
223        }
224        out
225    }
226}
227
228#[cfg(test)]
229mod tests {
230    use super::*;
231
232    #[test]
233    fn test_binary_reader_read() {
234        let mut reader = BinaryReader::from_bytes(&vec![0, 0, 1, 2, 3, 67, 89, 44]);
235        assert_eq!(reader.read(2).unwrap(), vec![0, 0]);
236        assert_eq!(reader.pos(), 2);
237        reader.seek(4).unwrap();
238        assert_eq!(reader.read(2).unwrap(), vec![3, 67]);
239        assert_eq!(reader.pos(), 6);
240        reader.seek_relative(-3).unwrap();
241        assert_eq!(reader.read(3).unwrap(), vec![2, 3, 67]);
242    }
243    #[test]
244    fn test_binary_reader_read_strings() {
245        let mut reader = BinaryReader::from_bytes(&vec![
246            0x61, 0x70, 0x70, 0x6c, 0x65, 0x73, 0x00, // "apples\0"
247            0x62, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x73, 0x64, // "bananas"
248            0x61, 0x74, 0x61, 0x00, 0x0a, // "data\0\n"
249        ]);
250
251        let string1 = "apples".to_string();
252        let string2 = "bananas".to_string();
253        let string3 = "data\0\n".to_string();
254
255        assert_eq!(reader.read_string_ascii(), string1);
256        assert_eq!(reader.read_string_ascii_limited(7).unwrap(), string2);
257        assert_eq!(reader.read_string_ascii_limited(6).unwrap(), string3);
258    }
259}