Skip to main content

rd_rds/
cursor.rs

1use crate::Error;
2
3/// A read-only cursor over an in-memory byte slice.
4#[derive(Debug, Clone, Copy)]
5pub struct ByteCursor<'a> {
6    bytes: &'a [u8],
7    position: usize,
8}
9
10impl<'a> ByteCursor<'a> {
11    pub fn new(bytes: &'a [u8]) -> Self {
12        Self { bytes, position: 0 }
13    }
14
15    pub fn position(&self) -> usize {
16        self.position
17    }
18
19    pub fn remaining(&self) -> usize {
20        self.bytes.len().saturating_sub(self.position)
21    }
22
23    pub fn read_u8(&mut self) -> Result<u8, Error> {
24        Ok(self.read_exact(1)?[0])
25    }
26
27    pub fn read_be_u32(&mut self) -> Result<u32, Error> {
28        let offset = self.position;
29        let bytes = self.read_exact(4)?;
30        let mut raw = [0u8; 4];
31        raw.copy_from_slice(bytes);
32        debug_assert_eq!(self.position, offset + 4);
33        Ok(u32::from_be_bytes(raw))
34    }
35
36    pub fn read_be_u64(&mut self) -> Result<u64, Error> {
37        let offset = self.position;
38        let bytes = self.read_exact(8)?;
39        let mut raw = [0u8; 8];
40        raw.copy_from_slice(bytes);
41        debug_assert_eq!(self.position, offset + 8);
42        Ok(u64::from_be_bytes(raw))
43    }
44
45    pub fn read_be_i32(&mut self) -> Result<i32, Error> {
46        let offset = self.position;
47        let bytes = self.read_exact(4)?;
48        let mut raw = [0u8; 4];
49        raw.copy_from_slice(bytes);
50        debug_assert_eq!(self.position, offset + 4);
51        Ok(i32::from_be_bytes(raw))
52    }
53
54    pub fn read_exact(&mut self, len: usize) -> Result<&'a [u8], Error> {
55        let offset = self.position;
56        let end = offset.checked_add(len).ok_or(Error::UnexpectedEof {
57            offset,
58            needed: len,
59            remaining: self.remaining(),
60        })?;
61        if end > self.bytes.len() {
62            return Err(Error::UnexpectedEof {
63                offset,
64                needed: len,
65                remaining: self.remaining(),
66            });
67        }
68        self.position = end;
69        Ok(&self.bytes[offset..end])
70    }
71}