Skip to main content

rustbac_core/encoding/
writer.rs

1use crate::EncodeError;
2
3/// A byte writer that encodes into a caller-owned buffer.
4///
5/// Tracks the write position and returns [`EncodeError::BufferTooSmall`] if
6/// the buffer is exhausted.
7#[derive(Debug)]
8pub struct Writer<'a> {
9    buf: &'a mut [u8],
10    pos: usize,
11}
12
13impl<'a> Writer<'a> {
14    pub fn new(buf: &'a mut [u8]) -> Self {
15        Self { buf, pos: 0 }
16    }
17
18    pub const fn position(&self) -> usize {
19        self.pos
20    }
21
22    pub fn remaining(&self) -> usize {
23        self.buf.len().saturating_sub(self.pos)
24    }
25
26    pub fn as_written(&self) -> &[u8] {
27        &self.buf[..self.pos]
28    }
29
30    pub fn write_u8(&mut self, value: u8) -> Result<(), EncodeError> {
31        if self.remaining() < 1 {
32            return Err(EncodeError::BufferTooSmall);
33        }
34        self.buf[self.pos] = value;
35        self.pos += 1;
36        Ok(())
37    }
38
39    pub fn write_all(&mut self, data: &[u8]) -> Result<(), EncodeError> {
40        if self.remaining() < data.len() {
41            return Err(EncodeError::BufferTooSmall);
42        }
43        let end = self.pos + data.len();
44        self.buf[self.pos..end].copy_from_slice(data);
45        self.pos = end;
46        Ok(())
47    }
48
49    pub fn write_be_u16(&mut self, value: u16) -> Result<(), EncodeError> {
50        self.write_all(&value.to_be_bytes())
51    }
52
53    pub fn write_be_u32(&mut self, value: u32) -> Result<(), EncodeError> {
54        self.write_all(&value.to_be_bytes())
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::Writer;
61    use crate::EncodeError;
62
63    #[test]
64    fn writer_writes_values() {
65        let mut buf = [0u8; 4];
66        let mut w = Writer::new(&mut buf);
67        w.write_u8(1).unwrap();
68        w.write_all(&[2, 3]).unwrap();
69        assert_eq!(w.as_written(), &[1, 2, 3]);
70    }
71
72    #[test]
73    fn writer_bounds() {
74        let mut buf = [0u8; 1];
75        let mut w = Writer::new(&mut buf);
76        w.write_u8(1).unwrap();
77        assert_eq!(w.write_u8(2).unwrap_err(), EncodeError::BufferTooSmall);
78    }
79}