1use crate::error::ParseError;
17
18#[derive(Debug, Copy, Clone, Eq, PartialEq)]
34pub struct SliceReader<'a> {
35 buf: &'a [u8],
36 offset: usize,
37}
38
39impl<'a> SliceReader<'a> {
40 #[inline(always)]
41 pub fn new(buf: &'a [u8]) -> Self {
42 Self { buf, offset: 0 }
43 }
44
45 #[cfg(test)]
46 pub fn new_with_offset(offset: usize, buf: &'a [u8]) -> Self {
47 Self { buf, offset }
48 }
49
50 #[inline(always)]
51 pub fn offset(&self) -> usize {
52 self.offset
53 }
54
55 #[inline(always)]
56 pub fn remaining(&self) -> usize {
57 self.buf.len()
58 }
59
60 #[inline(always)]
61 pub fn is_empty(&self) -> bool {
62 self.buf.is_empty()
63 }
64
65 #[inline(always)]
67 pub fn as_slice(&self) -> &'a [u8] {
68 self.buf
69 }
70
71 #[inline(always)]
72 pub fn read_u8(&mut self) -> Result<u8, ParseError> {
73 match self.buf.split_first() {
74 Some((&v, rest)) => {
75 self.buf = rest;
76 self.offset += 1;
77 Ok(v)
78 }
79 None => Err(ParseError::eof(self.offset, 1, 0)),
80 }
81 }
82
83 #[inline(always)]
85 pub fn read_array<const N: usize>(&mut self) -> Result<[u8; N], ParseError> {
86 match self.buf.split_first_chunk::<N>() {
87 Some((chunk, rest)) => {
88 self.buf = rest;
89 self.offset += N;
90 Ok(*chunk)
91 }
92 None => Err(ParseError::eof(self.offset, N, self.buf.len())),
93 }
94 }
95
96 #[inline(always)]
97 pub fn read_u16_be(&mut self) -> Result<u16, ParseError> {
98 self.read_array::<2>().map(u16::from_be_bytes)
99 }
100
101 #[inline(always)]
102 pub fn read_u32_be(&mut self) -> Result<u32, ParseError> {
103 self.read_array::<4>().map(u32::from_be_bytes)
104 }
105
106 #[inline(always)]
107 pub fn read_u64_be(&mut self) -> Result<u64, ParseError> {
108 self.read_array::<8>().map(u64::from_be_bytes)
109 }
110
111 #[inline(always)]
112 pub fn read_u128_be(&mut self) -> Result<u128, ParseError> {
113 self.read_array::<16>().map(u128::from_be_bytes)
114 }
115
116 #[inline(always)]
117 pub fn read_i32_be(&mut self) -> Result<i32, ParseError> {
118 self.read_array::<4>().map(i32::from_be_bytes)
119 }
120
121 #[inline(always)]
122 pub fn read_i64_be(&mut self) -> Result<i64, ParseError> {
123 self.read_array::<8>().map(i64::from_be_bytes)
124 }
125
126 #[inline(always)]
127 pub fn read_f32_be(&mut self) -> Result<f32, ParseError> {
128 self.read_array::<4>().map(f32::from_be_bytes)
129 }
130
131 #[inline(always)]
132 pub fn read_f64_be(&mut self) -> Result<f64, ParseError> {
133 self.read_array::<8>().map(f64::from_be_bytes)
134 }
135
136 #[inline]
143 pub fn read_bytes(&mut self, len: usize) -> Result<&'a [u8], ParseError> {
144 match self.buf.split_at_checked(len) {
145 Some((head, tail)) => {
146 self.buf = tail;
147 self.offset += len;
148 Ok(head)
149 }
150 None => Err(ParseError::eof(self.offset, len, self.buf.len())),
151 }
152 }
153
154 #[inline]
157 pub fn take_slice(&mut self, len: usize) -> Result<SliceReader<'a>, ParseError> {
158 let start = self.offset;
159 self.read_bytes(len)
160 .map(|buf| SliceReader { buf, offset: start })
161 }
162
163 #[inline(always)]
164 pub fn peek_u8(&mut self) -> Result<u8, ParseError> {
165 match self.buf.split_first() {
166 Some((&v, _rest)) => Ok(v),
167 None => Err(ParseError::eof(self.offset, 1, 0)),
168 }
169 }
170
171 #[inline(always)]
172 pub fn peek_u16_be(&self) -> Result<u16, ParseError> {
173 self.peek_array::<2>().map(u16::from_be_bytes)
174 }
175
176 #[inline(always)]
177 pub fn peek_u32_be(&self) -> Result<u32, ParseError> {
178 self.peek_array::<4>().map(u32::from_be_bytes)
179 }
180
181 #[inline(always)]
183 pub fn peek_array<const N: usize>(&self) -> Result<[u8; N], ParseError> {
184 self.buf
185 .first_chunk::<N>()
186 .copied()
187 .ok_or_else(|| ParseError::eof(self.offset, N, self.buf.len()))
188 }
189
190 #[inline]
192 pub fn read_padded<const N: usize>(&mut self, len: usize) -> Result<[u8; N], ParseError> {
193 if len > N {
194 return Err(ParseError::invalid_padding_length(self.offset, len, N));
195 }
196 let src = self.read_bytes(len)?;
197 let mut out = [0u8; N];
198 out[..len].copy_from_slice(src);
199 Ok(out)
200 }
201
202 #[inline]
214 pub fn read_unsigned32_be(&mut self, len: usize) -> Result<u32, ParseError> {
215 Ok(match len {
216 0 => 0,
217 1 => u32::from(self.read_array::<1>()?[0]),
218 2 => u32::from(u16::from_be_bytes(self.read_array::<2>()?)),
219 3 => {
220 let b = self.read_array::<3>()?;
221 u32::from_be_bytes([0, b[0], b[1], b[2]])
222 }
223 4 => u32::from_be_bytes(self.read_array::<4>()?),
224 _ => return Err(ParseError::invalid_padding_length(self.offset, len, 4)),
225 })
226 }
227 #[inline]
239 pub fn read_unsigned64_be(&mut self, len: usize) -> Result<u64, ParseError> {
240 Ok(match len {
241 0 => 0,
242 1 => u64::from(self.read_array::<1>()?[0]),
243 2 => u64::from(u16::from_be_bytes(self.read_array::<2>()?)),
244 3 => {
245 let b = self.read_array::<3>()?;
246 u64::from(u32::from_be_bytes([0, b[0], b[1], b[2]]))
247 }
248 4 => u64::from(u32::from_be_bytes(self.read_array::<4>()?)),
249 5 => {
250 let b = self.read_array::<5>()?;
251 u64::from_be_bytes([0, 0, 0, b[0], b[1], b[2], b[3], b[4]])
252 }
253 6 => {
254 let b = self.read_array::<6>()?;
255 u64::from_be_bytes([0, 0, b[0], b[1], b[2], b[3], b[4], b[5]])
256 }
257 7 => {
258 let b = self.read_array::<7>()?;
259 u64::from_be_bytes([0, b[0], b[1], b[2], b[3], b[4], b[5], b[6]])
260 }
261 8 => u64::from_be_bytes(self.read_array::<8>()?),
262 _ => return Err(ParseError::invalid_padding_length(self.offset, len, 8)),
263 })
264 }
265
266 #[inline]
272 pub fn read_signed32_be(&mut self, len: usize) -> Result<i32, ParseError> {
273 let v = self.read_unsigned32_be(len)? as i32;
277 let shift = ((4 - len) * 8) & 31; Ok((v << shift) >> shift)
279 }
280
281 #[inline]
288 pub fn read_signed64_be(&mut self, len: usize) -> Result<i64, ParseError> {
289 let v = self.read_unsigned64_be(len)? as i64;
293 let shift = ((8 - len) * 8) & 63; Ok((v << shift) >> shift)
295 }
296}
297
298#[cfg(test)]
299mod tests {
300 use super::*;
301
302 #[test]
303 fn reads_advance_and_track_offset() {
304 let data = [0x00, 0x01, 0x02, 0x03, 0x04];
305 let mut r = SliceReader::new(&data);
306 assert_eq!(r.read_u8(), Ok(0x00));
307 assert_eq!(r.read_u16_be(), Ok(0x0102));
308 assert_eq!(r.offset(), 3);
309 assert_eq!(r.remaining(), 2);
310 }
311
312 #[test]
313 fn eof_reports_offset_needed_available() {
314 let data = [0xAA, 0xBB];
315 let mut r = SliceReader::new(&data);
316 let _ = r.read_u8().unwrap();
317 let err = r.read_u32_be();
318 assert_eq!(err, Err(ParseError::eof(1, 4, 1)));
319 assert_eq!(err.map_err(|x| x.is_incomplete()), Err(true));
320 }
321
322 #[test]
323 fn copy_gives_free_checkpoint() {
324 let data = [1, 2, 3, 4];
325 let mut r = SliceReader::new(&data);
326 let save = r; let _ = r.read_u16_be().unwrap();
328 assert_eq!(r.offset(), 2);
329 r = save; assert_eq!(r.offset(), 0);
331 }
332
333 #[test]
334 fn peek_does_not_advance() {
335 let data = [0x12, 0x34];
336 let r = SliceReader::new(&data);
337 assert_eq!(r.peek_u16_be(), Ok(0x1234));
338 assert_eq!(r.offset(), 0);
339 }
340
341 #[test]
342 fn take_slice_carries_absolute_offset() {
343 let data = [0, 1, 2, 3, 4, 5];
344 let mut r = SliceReader::new(&data);
345 let _ = r.read_u16_be().unwrap();
346 let sub = r.take_slice(3);
347 assert_eq!(sub, Ok(SliceReader::new_with_offset(2, &[2, 3, 4])));
348 }
349
350 #[test]
351 fn len_equal_to_n_reads_full_no_padding() {
352 let data = [0xDE, 0xAD, 0xBE, 0xEF];
353 let mut r = SliceReader::new(&data);
354 let out = r.read_padded::<4>(4);
355 assert_eq!(out, Ok([0xDE, 0xAD, 0xBE, 0xEF]));
356 assert_eq!(r.offset(), 4);
357 assert_eq!(r.remaining(), 0);
358 }
359
360 #[test]
361 fn short_len_left_aligns_and_zero_pads_tail() {
362 let data = [0xAA, 0xBB, 0xCC];
363 let mut r = SliceReader::new(&data);
364 let out = r.read_padded::<4>(2);
365 assert_eq!(out, Ok([0xAA, 0xBB, 0x00, 0x00]));
366 assert_eq!(r.offset(), 2);
368 assert_eq!(r.as_slice(), &[0xCC]);
369 }
370
371 #[test]
372 fn zero_len_yields_all_zeros_without_advancing() {
373 let data = [0x11, 0x22];
374 let mut r = SliceReader::new(&data);
375 let out = r.read_padded::<4>(0);
376 assert_eq!(out, Ok([0, 0, 0, 0]));
377 assert_eq!(r.offset(), 0);
378 assert_eq!(r.remaining(), 2);
379 }
380
381 #[test]
382 fn len_within_n_but_buffer_too_short_is_eof() {
383 let data = [0xAA]; let mut r = SliceReader::new(&data);
385 let err = r.read_padded::<4>(3);
386 assert_eq!(err, Err(ParseError::eof(0, 3, 1)));
387 assert_eq!(r.offset(), 0); }
389
390 #[test]
391 fn capacity_error_reports_current_offset() {
392 let data = [0x00, 0x00, 0xAA, 0xBB, 0xCC];
393 let mut r = SliceReader::new(&data);
394 let _ = r.read_u16_be().unwrap(); let err = r.read_padded::<2>(5);
396 assert_eq!(err, Err(ParseError::invalid_padding_length(2, 5, 2)));
397 assert_eq!(r.offset(), 2); }
399
400 #[test]
401 fn uint_be_right_aligns_shortened_values() {
402 for wire in [
404 &[0xAB, 0xCD][..],
405 &[0x00, 0xAB, 0xCD],
406 &[0x00, 0x00, 0xAB, 0xCD],
407 ] {
408 let mut r = SliceReader::new(wire);
409 assert_eq!(r.read_unsigned64_be(wire.len()), Ok(0xABCD));
410 assert_eq!(r.remaining(), 0);
411 }
412 }
413
414 #[test]
415 fn uint_be_full_width_matches_fixed_read() {
416 let data = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF];
417 let mut a = SliceReader::new(&data);
418 let mut b = SliceReader::new(&data);
419 assert_eq!(a.read_unsigned64_be(8), b.read_u64_be());
420 }
421
422 #[test]
423 fn uint_be_zero_len_reads_nothing() {
424 let data = [0xAA];
425 let mut r = SliceReader::new(&data);
426 assert_eq!(r.read_unsigned64_be(0), Ok(0));
427 assert_eq!(r.offset(), 0);
428 }
429
430 #[test]
431 fn uint_be_rejects_len_beyond_width() {
432 let data = [0u8; 16];
433 let mut r = SliceReader::new(&data);
434 assert_eq!(
435 r.read_unsigned64_be(9),
436 Err(ParseError::invalid_padding_length(0, 9, 8))
437 );
438 assert_eq!(r.offset(), 0); }
440
441 #[test]
442 fn uint_be_short_buffer_is_eof() {
443 let data = [0xAA, 0xBB];
444 let mut r = SliceReader::new(&data);
445 assert_eq!(r.read_unsigned64_be(4), Err(ParseError::eof(0, 4, 2)));
446 }
447
448 #[test]
449 fn int_be_sign_extends_shortened_negative() {
450 let data = [0xFE];
452 let mut r = SliceReader::new(&data);
453 assert_eq!(r.read_signed64_be(1), Ok(-2));
454 }
455
456 #[test]
457 fn int_be_keeps_positive_values_unsigned() {
458 let data = [0x7F];
459 let mut r = SliceReader::new(&data);
460 assert_eq!(r.read_signed64_be(1), Ok(127));
461 }
462
463 #[test]
464 fn int_be_full_width_matches_fixed_read() {
465 let data = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE];
466 let mut a = SliceReader::new(&data);
467 let mut b = SliceReader::new(&data);
468 assert_eq!(a.read_signed64_be(8), b.read_i64_be());
469 assert_eq!(a.read_signed64_be(8), Err(ParseError::eof(8, 8, 0)));
470 }
471
472 #[test]
473 fn int_be_zero_len_is_not_negative() {
474 let data = [0xFF];
475 let mut r = SliceReader::new(&data);
476 assert_eq!(r.read_signed64_be(0), Ok(0));
478 assert_eq!(r.offset(), 0);
479 }
480
481 #[test]
482 fn uint32_be_right_aligns_shortened_values() {
483 for wire in [
485 &[0xAB, 0xCD][..],
486 &[0x00, 0xAB, 0xCD],
487 &[0x00, 0x00, 0xAB, 0xCD],
488 ] {
489 let mut r = SliceReader::new(wire);
490 assert_eq!(r.read_unsigned32_be(wire.len()), Ok(0xABCD));
491 assert_eq!(r.remaining(), 0);
492 }
493 }
494
495 #[test]
496 fn uint32_be_full_width_matches_fixed_read() {
497 let data = [0x01, 0x23, 0x45, 0x67];
498 let mut a = SliceReader::new(&data);
499 let mut b = SliceReader::new(&data);
500 assert_eq!(a.read_unsigned32_be(4), b.read_u32_be());
501 }
502
503 #[test]
504 fn uint32_be_zero_len_reads_nothing() {
505 let data = [0xAA];
506 let mut r = SliceReader::new(&data);
507 assert_eq!(r.read_unsigned32_be(0), Ok(0));
508 assert_eq!(r.offset(), 0);
509 }
510
511 #[test]
512 fn uint32_be_rejects_len_beyond_width() {
513 let data = [0u8; 16];
514 let mut r = SliceReader::new(&data);
515 assert_eq!(
516 r.read_unsigned32_be(5),
517 Err(ParseError::invalid_padding_length(0, 5, 4))
518 );
519 assert_eq!(r.offset(), 0); }
521
522 #[test]
523 fn uint32_be_short_buffer_is_eof() {
524 let data = [0xAA];
525 let mut r = SliceReader::new(&data);
526 assert_eq!(r.read_unsigned32_be(4), Err(ParseError::eof(0, 4, 1)));
527 }
528
529 #[test]
530 fn int32_be_sign_extends_shortened_negative() {
531 let data = [0xFE];
533 let mut r = SliceReader::new(&data);
534 assert_eq!(r.read_signed32_be(1), Ok(-2));
535 }
536
537 #[test]
538 fn int32_be_keeps_positive_values_unsigned() {
539 let data = [0x7F];
540 let mut r = SliceReader::new(&data);
541 assert_eq!(r.read_signed32_be(1), Ok(127));
542 }
543
544 #[test]
545 fn int32_be_full_width_matches_fixed_read() {
546 let data = [0xFF, 0xFF, 0xFF, 0xFE];
547 let mut a = SliceReader::new(&data);
548 let mut b = SliceReader::new(&data);
549 assert_eq!(a.read_signed32_be(4), b.read_i32_be());
550 assert_eq!(a.read_signed32_be(4), Err(ParseError::eof(4, 4, 0)));
551 }
552
553 #[test]
554 fn int32_be_zero_len_is_not_negative() {
555 let data = [0xFF];
556 let mut r = SliceReader::new(&data);
557 assert_eq!(r.read_signed32_be(0), Ok(0));
559 assert_eq!(r.offset(), 0);
560 }
561}