1use std::io::{Cursor, Read};
37use thiserror::Error;
38
39#[derive(Debug, Error)]
42pub enum BinaryCursorError {
43 #[error("Parse error: {0}")]
45 ParseError(#[from] std::io::Error),
46}
47
48impl BinaryCursorError {
49 pub fn from_io_error(error: std::io::Error) -> Self {
51 Self::ParseError(error)
52 }
53}
54#[derive(Debug)]
63pub struct BinaryCursor<T: AsRef<[u8]>> {
64 pub data: Cursor<T>,
66 location_stack: Vec<u32>,
68}
69
70impl<T> BinaryCursor<T>
71where
72 T: AsRef<[u8]>,
73{
74 pub fn new(data: T) -> Self {
76 Self {
77 data: Cursor::new(data),
78 location_stack: vec![],
79 }
80 }
81
82 pub fn push_location(&mut self) {
84 let pos = self.data.position() as u32;
85 self.location_stack.push(pos);
86 }
87
88 pub fn pop_location(&mut self) -> Option<u32> {
90 self.location_stack.pop()
91 }
92
93 pub fn restore_location(&mut self) -> bool {
97 if let Some(pos) = self.location_stack.pop() {
98 self.data.set_position(pos as u64);
99 true
100 } else {
101 false
102 }
103 }
104
105 pub fn parse_u8(&mut self) -> Result<u8, BinaryCursorError> {
107 let mut buf = [0u8; 1];
108 self.data.read_exact(&mut buf)?;
109 Ok(buf[0])
110 }
111
112 pub fn parse_u16_le(&mut self) -> Result<u16, BinaryCursorError> {
114 let mut buf = [0u8; 2];
115 self.data.read_exact(&mut buf)?;
116 Ok(u16::from_le_bytes(buf))
117 }
118
119 pub fn parse_u32_le(&mut self) -> Result<u32, BinaryCursorError> {
121 let mut buf = [0u8; 4];
122 self.data.read_exact(&mut buf)?;
123 Ok(u32::from_le_bytes(buf))
124 }
125
126 pub fn parse_f32_le(&mut self) -> Result<f32, BinaryCursorError> {
128 let mut buf = [0u8; 4];
129 self.data.read_exact(&mut buf)?;
130 Ok(f32::from_le_bytes(buf))
131 }
132
133 pub fn parse_bytes(&mut self, count: usize) -> Result<Vec<u8>, BinaryCursorError> {
135 let mut buf = vec![0u8; count];
136 self.data.read_exact(&mut buf)?;
137 Ok(buf)
138 }
139
140 pub fn position(&self) -> u64 {
142 self.data.position()
143 }
144
145 pub fn set_position(&mut self, pos: u64) {
147 self.data.set_position(pos);
148 }
149
150 pub fn count<U, F>(&mut self, mut parser: F, count: usize) -> Result<Vec<U>, BinaryCursorError>
166 where
167 F: FnMut(&mut Self) -> Result<U, BinaryCursorError>,
168 {
169 let mut items = Vec::with_capacity(count);
170 for _ in 0..count {
171 items.push(parser(self)?);
172 }
173 Ok(items)
174 }
175}
176pub struct BinaryCursorJump<'a, T: AsRef<[u8]>> {
185 pub cursor: &'a mut BinaryCursor<T>,
187}
188
189impl<'a, T> BinaryCursorJump<'a, T>
190where
191 T: AsRef<[u8]>,
192{
193 pub fn new(cursor: &'a mut BinaryCursor<T>) -> Self {
195 Self { cursor }
196 }
197
198 pub fn jump(&mut self, location: u64) -> Result<(), BinaryCursorError> {
202 self.cursor.push_location();
203 self.cursor.set_position(location);
204 Ok(())
205 }
206}
207
208impl<'a, T> Drop for BinaryCursorJump<'a, T>
209where
210 T: AsRef<[u8]>,
211{
212 fn drop(&mut self) {
213 self.cursor.restore_location();
214 }
215}
216#[cfg(test)]
220mod tests {
221 use super::*;
222
223 #[test]
224 fn test_parse_u8() {
225 let data = vec![0x42, 0x43, 0x44];
226 let mut cursor = BinaryCursor::new(data);
227 assert_eq!(cursor.parse_u8().unwrap(), 0x42);
228 assert_eq!(cursor.position(), 1);
229 }
230
231 #[test]
232 fn test_parse_u16_le() {
233 let data = vec![0x42, 0x24, 0x43, 0x25];
234 let mut cursor = BinaryCursor::new(data);
235 assert_eq!(cursor.parse_u16_le().unwrap(), 0x2442);
236 assert_eq!(cursor.position(), 2);
237 }
238
239 #[test]
240 fn test_parse_u32_le() {
241 let data = vec![0x42, 0x24, 0x00, 0x01, 0x43, 0x25, 0x01, 0x02];
242 let mut cursor = BinaryCursor::new(data);
243 assert_eq!(cursor.parse_u32_le().unwrap(), 0x01002442);
244 assert_eq!(cursor.position(), 4);
245 }
246
247 #[test]
248 fn test_parse_f32_le() {
249 let data = vec![0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x40];
250 let mut cursor = BinaryCursor::new(data);
251 assert_eq!(cursor.parse_f32_le().unwrap(), 1.0);
252 assert_eq!(cursor.position(), 4);
253 }
254
255 #[test]
256 fn test_parse_bytes() {
257 let data = vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
258 let mut cursor = BinaryCursor::new(data);
259 assert_eq!(cursor.parse_bytes(4).unwrap(), vec![0x01, 0x02, 0x03, 0x04]);
260 assert_eq!(cursor.position(), 4);
261 }
262
263 #[test]
264 fn test_location_stack() {
265 let data = vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
266 let mut cursor = BinaryCursor::new(data);
267
268 cursor.push_location();
269 cursor.set_position(4);
270 assert_eq!(cursor.position(), 4);
271
272 assert!(cursor.restore_location());
273 assert_eq!(cursor.position(), 0);
274 }
275
276 #[test]
277 fn test_binary_cursor_jump() {
278 let data = vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
279 let mut cursor = BinaryCursor::new(data);
280
281 {
282 let mut jump = BinaryCursorJump::new(&mut cursor);
283 jump.jump(4).unwrap();
284 assert_eq!(jump.cursor.position(), 4);
285 }
286
287 assert_eq!(cursor.position(), 0u64);
288 }
289
290 #[test]
291 fn test_sequential_parsing() {
292 let data = vec![0x42, 0x24, 0x00, 0x01, 0x43, 0x25, 0x01, 0x02];
293 let mut cursor = BinaryCursor::new(data);
294
295 assert_eq!(cursor.parse_u8().unwrap(), 0x42);
296 assert_eq!(cursor.position(), 1);
297
298 assert_eq!(cursor.parse_u16_le().unwrap(), 0x0024);
299 assert_eq!(cursor.position(), 3);
300
301 assert_eq!(cursor.parse_u32_le().unwrap(), 0x01254301);
302 assert_eq!(cursor.position(), 7);
303
304 assert!(cursor.parse_u8().is_ok());
305 assert_eq!(cursor.position(), 8);
306 }
307
308 #[test]
309 fn test_count() {
310 let data = vec![0x01, 0x02, 0x03, 0x04];
311 let mut cursor = BinaryCursor::new(data);
312 let result = cursor.count(|c| c.parse_u8(), 4).unwrap();
313 assert_eq!(result, vec![0x01, 0x02, 0x03, 0x04]);
314 assert_eq!(cursor.position(), 4);
315 }
316
317 #[test]
318 fn test_pop_location() {
319 let data = vec![0x01, 0x02, 0x03, 0x04];
320 let mut cursor = BinaryCursor::new(data);
321 assert_eq!(cursor.pop_location(), None);
322
323 cursor.push_location();
324 cursor.set_position(2);
325 assert_eq!(cursor.pop_location(), Some(0));
326 assert_eq!(cursor.position(), 2);
327 }
328
329 #[test]
330 fn test_error_handling() {
331 let data = vec![0x42];
332 let mut cursor = BinaryCursor::new(data);
333
334 assert!(cursor.parse_u16_le().is_err());
335 assert!(cursor.parse_u32_le().is_err());
336 assert!(cursor.parse_f32_le().is_err());
337 assert!(cursor.parse_bytes(2).is_err());
338 }
339
340 #[test]
341 fn test_restore_location() {
342 let data = vec![0x01, 0x02, 0x03, 0x04];
343 let mut cursor = BinaryCursor::new(data);
344
345 cursor.push_location();
346 cursor.set_position(2);
347 assert_eq!(cursor.position(), 2);
348
349 assert!(cursor.restore_location());
350 assert_eq!(cursor.position(), 0);
351
352 assert!(!cursor.restore_location());
353 }
354
355 #[test]
356 fn test_error_conversion() {
357 use std::io::{Error, ErrorKind};
358 let io_error = Error::new(ErrorKind::UnexpectedEof, "test error");
359 let cursor_error = BinaryCursorError::from_io_error(io_error);
360 match cursor_error {
361 BinaryCursorError::ParseError(_) => (),
362 }
363 }
364}
365