1use core::fmt;
2
3#[derive(Clone)]
5pub(crate) struct Reader<'data> {
6 index: usize,
8 data: &'data [u8],
9}
10
11#[derive(Debug, Clone)]
13pub(crate) struct RestorePoint(usize);
14
15impl<'data> Reader<'data> {
16 #[inline]
23 #[must_use]
24 pub(crate) const fn new(data: &'data [u8]) -> Self {
25 if data.len() == usize::MAX {
26 panic!("cannot create a Reader containing usize::MAX bytes");
27 }
28
29 Self { index: 0, data }
30 }
31
32 pub(crate) const fn get_restore_point(&self) -> RestorePoint {
35 RestorePoint(self.index)
36 }
37
38 pub(crate) fn restore(&mut self, restore: RestorePoint) {
40 self.index = restore.0;
41 }
42
43 pub(crate) fn skip_until_any(&mut self, needles: &[u8]) -> bool {
46 debug_assert_ne!(
47 needles.len(),
48 0,
49 "searching for any of 0 bytes makes no sense"
50 );
51
52 let position = self.data[self.index..]
53 .iter()
54 .position(|x| needles.contains(x));
55
56 if let Some(position) = position {
57 self.index += position;
58 }
59
60 position.is_some()
61 }
62
63 #[must_use]
65 pub(crate) const fn remaining(&self) -> usize {
66 self.data.len() - self.index
67 }
68
69 #[must_use]
72 #[cfg_attr(not(test), expect(dead_code))]
73 pub(crate) fn is_empty(&self) -> bool {
74 self.remaining() == 0
75 }
76
77 pub(crate) fn peek(&self) -> Option<u8> {
79 self.data.get(self.index).copied()
80 }
81
82 pub(crate) fn read_line(&mut self) -> Option<&'data [u8]> {
88 let start = self.index;
89
90 let rest = self.data.get(start..).filter(|x| !x.is_empty())?;
91
92 if let Some(len) = rest.iter().position(|b| *b == b'\n') {
93 self.index += len + 1; let end = start + len;
96 self.data.get(start..end)
97 } else {
98 self.index = self.data.len();
99 self.data.get(start..)
100 }
101 }
102
103 pub(crate) fn read_n_bytes(&mut self, n: usize) -> &'data [u8] {
106 let len = n.min(self.remaining());
107
108 let start = self.index;
109 let slice = &self.data[start..(start + len)];
110
111 self.index += len;
112 slice
113 }
114
115 pub(crate) fn read_u8(&mut self) -> Option<u8> {
117 let byte = self.peek();
118 if byte.is_some() {
119 self.index += 1;
120 }
121 byte
122 }
123
124 pub(crate) fn read_i8(&mut self) -> Option<i8> {
126 self.read_u8().map(u8::cast_signed)
127 }
128
129 pub(crate) fn read_u24(&mut self) -> Option<u32> {
131 if self.remaining() < 3 {
132 return None;
133 }
134
135 let mut bytes = [0; 4];
136 let slice = &mut bytes[0..3];
137
138 let start = self.index;
139 slice.copy_from_slice(&self.data[start..(start + 3)]);
140 self.index += 3;
141
142 Some(u32::from_le_bytes(bytes))
143 }
144
145 pub(crate) fn read_f32(&mut self) -> Option<f32> {
146 self.read_u32().map(f32::from_bits)
147 }
148}
149
150macro_rules! impl_read {
151 ($read:ident, $type:ty, $iread:ident, $itype:ty) => {
152 #[allow(dead_code)]
153 pub(crate) fn $read(&mut self) -> Option<$type> {
154 const BYTES: usize = (<$type>::BITS / 8) as usize;
155
156 if self.remaining() < BYTES {
157 return None;
158 }
159
160 let mut bytes = [0; BYTES];
161 let start = self.index;
162 bytes.copy_from_slice(&self.data[start..(start + BYTES)]);
163 self.index += BYTES;
164
165 Some(<$type>::from_le_bytes(bytes))
166 }
167
168 #[allow(dead_code)]
169 pub(crate) fn $iread(&mut self) -> Option<$itype> {
170 #[expect(clippy::cast_possible_wrap)]
171 self.$read().map(|x| x as $itype)
172 }
173 };
174}
175
176impl Reader<'_> {
177 impl_read!(read_u16, u16, read_i16, i16);
178
179 impl_read!(read_u32, u32, read_i32, i32);
180
181 impl_read!(read_u64, u64, read_i64, i64);
182
183 impl_read!(read_u128, u128, read_i128, i128);
184}
185
186impl fmt::Debug for Reader<'_> {
187 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188 f.debug_struct("Reader")
189 .field("index", &self.index)
190 .finish_non_exhaustive()
191 }
192}
193
194#[cfg(test)]
195mod tests {
196 use super::*;
197
198 #[test]
199 fn restore() {
200 let mut bytes = Reader::new(&[0, 1, 2]);
201 bytes.read_u8();
202 let restore = bytes.get_restore_point();
203 bytes.read_u16();
204 assert!(bytes.is_empty());
205 bytes.restore(restore);
206 assert_eq!(Some(1), bytes.read_u8());
207 }
208
209 #[test]
210 fn skip_until_any() {
211 let mut bytes = Reader::new(&[10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
212 bytes.read_u8();
213 assert!(bytes.skip_until_any(&[10, 9]));
214 assert_eq!(Some(9), bytes.read_u8());
215 }
216
217 #[test]
218 fn skip_until_any_not_found() {
219 let mut bytes = Reader::new(&[2, 3, 4]);
220 assert!(!bytes.skip_until_any(&[0, 1]));
221 }
222
223 #[test]
224 fn skip_until_any_no_skip() {
225 let mut bytes = Reader::new(&[0]);
226 assert!(bytes.skip_until_any(&[0]));
227 assert_eq!(Some(0), bytes.read_u8());
228 assert!(bytes.is_empty());
229 }
230
231 #[test]
232 fn read_u16() {
233 let mut bytes = Reader::new(&[0x39, 0x05]);
234 assert_eq!(Some(0x0539), bytes.read_u16());
235 }
236
237 #[test]
238 fn read_i16() {
239 let mut bytes = Reader::new(&[0xC7, 0xFA]);
240 assert_eq!(Some(-0x0539), bytes.read_i16());
241 }
242
243 #[test]
244 fn read_u24() {
245 let mut bytes = Reader::new(&[0x56, 0x34, 0x12]);
246 assert_eq!(Some(0x123456), bytes.read_u24());
247 }
248
249 #[test]
250 fn read_u32() {
251 let mut bytes = Reader::new(&[0xEF, 0xCD, 0x34, 0x12]);
252 assert_eq!(Some(0x1234_CDEF), bytes.read_u32());
253 }
254
255 #[test]
256 fn read_i32() {
257 let mut bytes = Reader::new(&[0x11, 0x32, 0xCB, 0xED]);
258 assert_eq!(Some(-0x1234_CDEF), bytes.read_i32());
259 }
260
261 #[test]
262 fn read_u64() {
263 let mut bytes = Reader::new(&[0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01]);
264 assert_eq!(Some(0x0123_4567_89AB_CDEF), bytes.read_u64());
265 }
266
267 #[test]
268 fn read_i64() {
269 let mut bytes = Reader::new(&[1, 0, 0, 0, 0, 0, 0, 0x80]);
270 assert_eq!(Some(i64::MIN + 1), bytes.read_i64());
271 }
272
273 #[test]
274 fn read_u128() {
275 let mut bytes = Reader::new(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF]);
276 assert_eq!(
277 Some(0x0F0E_0D0C_0B0A_0908_0706_0504_0302_0100),
278 bytes.read_u128()
279 );
280 }
281
282 #[test]
283 fn read_i128() {
284 let mut bytes = Reader::new(&[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80]);
285 assert_eq!(Some(i128::MIN + 1), bytes.read_i128());
286 }
287
288 #[test]
289 fn bytes_read_line() {
290 let mut bytes = Reader::new(&[b'a', 0, b'\n', b'b']);
291
292 assert_eq!(Some(b"a\0".as_ref()), bytes.read_line());
293 assert_eq!(Some(b'b'), bytes.read_u8());
294 }
295
296 #[test]
297 fn bytes_read_n_bytes_exact() {
298 let input = [0, 1, 2, 3];
299
300 let mut bytes = Reader::new(&input);
301
302 let read = bytes.read_n_bytes(1);
303 assert_eq!(read.len(), 1);
304 assert_eq!(read, &input[0..1]);
305
306 let read = bytes.read_n_bytes(0);
307 assert_eq!(read.len(), 0);
308
309 let read = bytes.read_n_bytes(3);
310 assert_eq!(read.len(), 3);
311 assert_eq!(read, &input[1..]);
312
313 assert!(bytes.is_empty());
314 }
315
316 #[test]
317 fn bytes_read_n_bytes_overshoot() {
318 let input = [0];
319
320 let mut bytes = Reader::new(&input);
321
322 let read = bytes.read_n_bytes(2);
323 assert_eq!(read.len(), 1);
324 assert_eq!(read, input);
325
326 assert!(bytes.is_empty());
327 }
328
329 #[test]
330 fn bytes_read_line_without_newline() {
331 let mut bytes = Reader::new(&[b'a', 0]);
332
333 assert_eq!(Some(b"a\0".as_ref()), bytes.read_line());
334 assert_eq!(None, bytes.read_u8());
335 }
336
337 #[test]
338 fn bytes_read_line_empty() {
339 let mut bytes = Reader::new(&[]);
340 assert_eq!(None, bytes.read_line());
341 }
342}