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 {
13 Self { buf, pos: 0 }
14 }
15
16 pub const fn position(&self) -> usize {
18 self.pos
19 }
20
21 pub fn remaining(&self) -> usize {
23 self.buf.len().saturating_sub(self.pos)
24 }
25
26 pub fn is_empty(&self) -> bool {
28 self.remaining() == 0
29 }
30
31 pub fn peek_u8(&self) -> Result<u8, DecodeError> {
33 self.buf
34 .get(self.pos)
35 .copied()
36 .ok_or(DecodeError::UnexpectedEof)
37 }
38
39 pub fn read_u8(&mut self) -> Result<u8, DecodeError> {
41 let byte = self.peek_u8()?;
42 self.pos += 1;
43 Ok(byte)
44 }
45
46 pub fn read_exact(&mut self, len: usize) -> Result<&'a [u8], DecodeError> {
48 if self.remaining() < len {
49 return Err(DecodeError::UnexpectedEof);
50 }
51 let start = self.pos;
52 self.pos += len;
53 Ok(&self.buf[start..start + len])
54 }
55
56 pub fn read_be_u16(&mut self) -> Result<u16, DecodeError> {
58 let bytes = self.read_exact(2)?;
59 Ok(u16::from_be_bytes([bytes[0], bytes[1]]))
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::Reader;
66 use crate::DecodeError;
67
68 #[test]
69 fn reader_reads_values() {
70 let mut r = Reader::new(&[1, 2, 3, 4]);
71 assert_eq!(r.read_u8().unwrap(), 1);
72 assert_eq!(r.read_exact(2).unwrap(), &[2, 3]);
73 assert_eq!(r.read_be_u16().unwrap_err(), DecodeError::UnexpectedEof);
74 }
75
76 #[test]
77 fn reader_position_and_remaining() {
78 let mut r = Reader::new(&[0x12, 0x34, 0x56]);
79 assert_eq!(r.position(), 0);
80 assert_eq!(r.remaining(), 3);
81 assert_eq!(r.peek_u8().unwrap(), 0x12);
82 assert_eq!(r.read_u8().unwrap(), 0x12);
83 assert_eq!(r.position(), 1);
84 assert_eq!(r.read_be_u16().unwrap(), 0x3456);
85 assert!(r.is_empty());
86 }
87}