1use crate::error::{Error, Result};
2use crate::header::ByteOrder;
3
4pub struct Cursor<'a> {
6 data: &'a [u8],
7 pos: usize,
8 byte_order: ByteOrder,
9}
10
11impl<'a> Cursor<'a> {
12 pub fn new(data: &'a [u8], byte_order: ByteOrder) -> Self {
13 Self {
14 data,
15 pos: 0,
16 byte_order,
17 }
18 }
19
20 pub fn with_offset(data: &'a [u8], offset: usize, byte_order: ByteOrder) -> Result<Self> {
21 if offset > data.len() {
22 return Err(Error::Truncated {
23 offset: offset as u64,
24 needed: 0,
25 available: data.len() as u64,
26 });
27 }
28 Ok(Self {
29 data,
30 pos: offset,
31 byte_order,
32 })
33 }
34
35 pub fn position(&self) -> usize {
36 self.pos
37 }
38
39 pub fn remaining(&self) -> usize {
40 self.data.len().saturating_sub(self.pos)
41 }
42
43 pub fn read_u8(&mut self) -> Result<u8> {
44 self.ensure(1)?;
45 let v = self.data[self.pos];
46 self.pos += 1;
47 Ok(v)
48 }
49
50 pub fn read_u16(&mut self) -> Result<u16> {
51 self.ensure(2)?;
52 let bytes = [self.data[self.pos], self.data[self.pos + 1]];
53 self.pos += 2;
54 Ok(match self.byte_order {
55 ByteOrder::LittleEndian => u16::from_le_bytes(bytes),
56 ByteOrder::BigEndian => u16::from_be_bytes(bytes),
57 })
58 }
59
60 pub fn read_u32(&mut self) -> Result<u32> {
61 self.ensure(4)?;
62 let bytes: [u8; 4] = self.data[self.pos..self.pos + 4].try_into().unwrap();
63 self.pos += 4;
64 Ok(match self.byte_order {
65 ByteOrder::LittleEndian => u32::from_le_bytes(bytes),
66 ByteOrder::BigEndian => u32::from_be_bytes(bytes),
67 })
68 }
69
70 pub fn read_u64(&mut self) -> Result<u64> {
71 self.ensure(8)?;
72 let bytes: [u8; 8] = self.data[self.pos..self.pos + 8].try_into().unwrap();
73 self.pos += 8;
74 Ok(match self.byte_order {
75 ByteOrder::LittleEndian => u64::from_le_bytes(bytes),
76 ByteOrder::BigEndian => u64::from_be_bytes(bytes),
77 })
78 }
79
80 pub fn read_f64(&mut self) -> Result<f64> {
81 self.ensure(8)?;
82 let bytes: [u8; 8] = self.data[self.pos..self.pos + 8].try_into().unwrap();
83 self.pos += 8;
84 Ok(match self.byte_order {
85 ByteOrder::LittleEndian => f64::from_le_bytes(bytes),
86 ByteOrder::BigEndian => f64::from_be_bytes(bytes),
87 })
88 }
89
90 pub fn read_bytes(&mut self, n: usize) -> Result<&'a [u8]> {
91 self.ensure(n)?;
92 let slice = &self.data[self.pos..self.pos + n];
93 self.pos += n;
94 Ok(slice)
95 }
96
97 pub fn skip(&mut self, n: usize) -> Result<()> {
98 self.ensure(n)?;
99 self.pos += n;
100 Ok(())
101 }
102
103 fn ensure(&self, n: usize) -> Result<()> {
104 if self.pos + n > self.data.len() {
105 return Err(Error::Truncated {
106 offset: self.pos as u64,
107 needed: n as u64,
108 available: self.data.len().saturating_sub(self.pos) as u64,
109 });
110 }
111 Ok(())
112 }
113}