rustmod_core/encoding/
reader.rs1use crate::DecodeError;
2
3#[derive(Debug, Clone, Copy)]
5pub struct Reader<'a> {
6 buf: &'a [u8],
7 pos: usize,
8}
9
10impl<'a> Reader<'a> {
11 pub const fn new(buf: &'a [u8]) -> Self {
12 Self { buf, pos: 0 }
13 }
14
15 pub const fn position(&self) -> usize {
16 self.pos
17 }
18
19 pub fn remaining(&self) -> usize {
20 self.buf.len().saturating_sub(self.pos)
21 }
22
23 pub fn is_empty(&self) -> bool {
24 self.remaining() == 0
25 }
26
27 pub fn peek_u8(&self) -> Result<u8, DecodeError> {
28 self.buf
29 .get(self.pos)
30 .copied()
31 .ok_or(DecodeError::UnexpectedEof)
32 }
33
34 pub fn read_u8(&mut self) -> Result<u8, DecodeError> {
35 let byte = self.peek_u8()?;
36 self.pos += 1;
37 Ok(byte)
38 }
39
40 pub fn read_exact(&mut self, len: usize) -> Result<&'a [u8], DecodeError> {
41 if self.remaining() < len {
42 return Err(DecodeError::UnexpectedEof);
43 }
44 let start = self.pos;
45 self.pos += len;
46 Ok(&self.buf[start..start + len])
47 }
48
49 pub fn read_be_u16(&mut self) -> Result<u16, DecodeError> {
50 let bytes = self.read_exact(2)?;
51 Ok(u16::from_be_bytes([bytes[0], bytes[1]]))
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::Reader;
58 use crate::DecodeError;
59
60 #[test]
61 fn reader_reads_values() {
62 let mut r = Reader::new(&[1, 2, 3, 4]);
63 assert_eq!(r.read_u8().unwrap(), 1);
64 assert_eq!(r.read_exact(2).unwrap(), &[2, 3]);
65 assert_eq!(r.read_be_u16().unwrap_err(), DecodeError::UnexpectedEof);
66 }
67
68 #[test]
69 fn reader_position_and_remaining() {
70 let mut r = Reader::new(&[0x12, 0x34, 0x56]);
71 assert_eq!(r.position(), 0);
72 assert_eq!(r.remaining(), 3);
73 assert_eq!(r.peek_u8().unwrap(), 0x12);
74 assert_eq!(r.read_u8().unwrap(), 0x12);
75 assert_eq!(r.position(), 1);
76 assert_eq!(r.read_be_u16().unwrap(), 0x3456);
77 assert!(r.is_empty());
78 }
79}