Skip to main content

rustmod_core/encoding/
writer.rs

1use crate::EncodeError;
2
3/// A byte writer that encodes into a caller-owned buffer.
4#[derive(Debug)]
5pub struct Writer<'a> {
6    buf: &'a mut [u8],
7    pos: usize,
8}
9
10impl<'a> Writer<'a> {
11    pub fn new(buf: &'a mut [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 as_written(&self) -> &[u8] {
24        &self.buf[..self.pos]
25    }
26
27    pub fn write_u8(&mut self, value: u8) -> Result<(), EncodeError> {
28        if self.remaining() < 1 {
29            return Err(EncodeError::BufferTooSmall);
30        }
31        self.buf[self.pos] = value;
32        self.pos += 1;
33        Ok(())
34    }
35
36    pub fn write_all(&mut self, data: &[u8]) -> Result<(), EncodeError> {
37        if self.remaining() < data.len() {
38            return Err(EncodeError::BufferTooSmall);
39        }
40        let end = self.pos + data.len();
41        self.buf[self.pos..end].copy_from_slice(data);
42        self.pos = end;
43        Ok(())
44    }
45
46    pub fn write_be_u16(&mut self, value: u16) -> Result<(), EncodeError> {
47        self.write_all(&value.to_be_bytes())
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::Writer;
54    use crate::EncodeError;
55
56    #[test]
57    fn writer_writes_values() {
58        let mut buf = [0u8; 4];
59        let mut w = Writer::new(&mut buf);
60        w.write_u8(0x12).unwrap();
61        w.write_be_u16(0x3456).unwrap();
62        assert_eq!(w.as_written(), &[0x12, 0x34, 0x56]);
63    }
64
65    #[test]
66    fn writer_bounds() {
67        let mut buf = [0u8; 2];
68        let mut w = Writer::new(&mut buf);
69        w.write_be_u16(0x1234).unwrap();
70        assert_eq!(w.write_u8(0).unwrap_err(), EncodeError::BufferTooSmall);
71    }
72}