lvm_common/utils/
cursor.rs1use std::fmt::Display;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum ByteOrder {
5 BigEndian,
6 LittleEndian,
7}
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum CursorError {
11 UnexpectedEof,
12}
13
14impl Display for CursorError {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 match self {
17 CursorError::UnexpectedEof => write!(f, "Unexpected end of input"),
18 }
19 }
20}
21
22pub struct ByteCursor<'a> {
23 data: &'a [u8],
24 pos: usize,
25 order: ByteOrder,
26}
27
28impl<'a> ByteCursor<'a> {
29 #[inline]
30 pub fn new(data: &'a [u8]) -> Self {
31 Self {
32 data,
33 pos: 0,
34 order: ByteOrder::BigEndian,
35 }
36 }
37
38 #[inline]
39 pub fn with_order(data: &'a [u8], order: ByteOrder) -> Self {
40 Self {
41 data,
42 pos: 0,
43 order,
44 }
45 }
46
47 #[inline]
48 pub fn order(&self) -> ByteOrder {
49 self.order
50 }
51 #[inline]
52 pub fn position(&self) -> usize {
53 self.pos
54 }
55 #[inline]
56 pub fn remaining(&self) -> usize {
57 self.data.len().saturating_sub(self.pos)
58 }
59 #[inline]
60 pub fn is_eof(&self) -> bool {
61 self.pos >= self.data.len()
62 }
63
64 #[inline]
65 pub fn skip(&mut self, n: usize) -> Result<(), CursorError> {
66 if self.remaining() < n {
67 return Err(CursorError::UnexpectedEof);
68 }
69 self.pos += n;
70 Ok(())
71 }
72
73 #[inline]
74 pub fn align(&mut self, align: usize) -> Result<(), CursorError> {
75 let mis = self.pos % align;
76 if mis == 0 {
77 return Ok(());
78 }
79 self.skip(align - mis)
80 }
81
82 #[inline]
83 pub fn slice(&mut self, n: usize) -> Result<&'a [u8], CursorError> {
84 if self.remaining() < n {
85 return Err(CursorError::UnexpectedEof);
86 }
87 let s = &self.data[self.pos..self.pos + n];
88 self.pos += n;
89 Ok(s)
90 }
91
92 #[inline]
93 pub fn bytes(&mut self, n: usize) -> Result<&[u8], CursorError> {
94 self.slice(n)
95 }
96
97 #[inline]
98 fn take<const N: usize>(&mut self) -> Result<&'a [u8; N], CursorError> {
99 if self.remaining() < N {
100 return Err(CursorError::UnexpectedEof);
101 }
102 let p = self.pos;
103 self.pos += N;
104 let ptr = &self.data[p] as *const u8 as *const [u8; N];
105 Ok(unsafe { &*ptr })
106 }
107
108 #[inline]
109 pub fn u8(&mut self) -> Result<u8, CursorError> {
110 self.take::<1>().map(|b| b[0])
111 }
112 #[inline]
113 pub fn i8(&mut self) -> Result<i8, CursorError> {
114 self.u8().map(|v| v as i8)
115 }
116
117 #[inline]
118 pub fn u16(&mut self) -> Result<u16, CursorError> {
119 let b = self.take::<2>()?;
120 Ok(match self.order {
121 ByteOrder::BigEndian => u16::from_be_bytes(*b),
122 ByteOrder::LittleEndian => u16::from_le_bytes(*b),
123 })
124 }
125
126 #[inline]
127 pub fn i16(&mut self) -> Result<i16, CursorError> {
128 self.u16().map(|v| v as i16)
129 }
130
131 #[inline]
132 pub fn u32(&mut self) -> Result<u32, CursorError> {
133 let b = self.take::<4>()?;
134 Ok(match self.order {
135 ByteOrder::BigEndian => u32::from_be_bytes(*b),
136 ByteOrder::LittleEndian => u32::from_le_bytes(*b),
137 })
138 }
139
140 #[inline]
141 pub fn i32(&mut self) -> Result<i32, CursorError> {
142 self.u32().map(|v| v as i32)
143 }
144
145 #[inline]
146 pub fn u64(&mut self) -> Result<u64, CursorError> {
147 let b = self.take::<8>()?;
148 Ok(match self.order {
149 ByteOrder::BigEndian => u64::from_be_bytes(*b),
150 ByteOrder::LittleEndian => u64::from_le_bytes(*b),
151 })
152 }
153
154 #[inline]
155 pub fn i64(&mut self) -> Result<i64, CursorError> {
156 self.u64().map(|v| v as i64)
157 }
158
159 #[inline]
160 pub fn f32(&mut self) -> Result<f32, CursorError> {
161 self.u32().map(f32::from_bits)
162 }
163 #[inline]
164 pub fn f64(&mut self) -> Result<f64, CursorError> {
165 self.u64().map(f64::from_bits)
166 }
167
168 #[inline]
169 pub fn try_u8(&mut self) -> Option<u8> {
170 if self.remaining() == 0 {
171 None
172 } else {
173 let b = self.data[self.pos];
174 self.pos += 1;
175 Some(b)
176 }
177 }
178
179 #[inline]
180 pub fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), CursorError> {
181 let n = buf.len();
182 if self.remaining() < n {
183 return Err(CursorError::UnexpectedEof);
184 }
185
186 buf.copy_from_slice(&self.data[self.pos..self.pos + n]);
187 self.pos += n;
188 Ok(())
189 }
190}