Skip to main content

lvm_common/utils/
cursor.rs

1use 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}