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    /// Create a writer over the given mutable byte slice.
12    pub fn new(buf: &'a mut [u8]) -> Self {
13        Self { buf, pos: 0 }
14    }
15
16    /// Number of bytes written so far.
17    pub const fn position(&self) -> usize {
18        self.pos
19    }
20
21    /// Number of bytes remaining in the buffer.
22    pub fn remaining(&self) -> usize {
23        self.buf.len().saturating_sub(self.pos)
24    }
25
26    /// View the bytes written so far.
27    pub fn as_written(&self) -> &[u8] {
28        &self.buf[..self.pos]
29    }
30
31    /// Write a single byte.
32    pub fn write_u8(&mut self, value: u8) -> Result<(), EncodeError> {
33        if self.remaining() < 1 {
34            return Err(EncodeError::BufferTooSmall);
35        }
36        self.buf[self.pos] = value;
37        self.pos += 1;
38        Ok(())
39    }
40
41    /// Write a byte slice.
42    pub fn write_all(&mut self, data: &[u8]) -> Result<(), EncodeError> {
43        if self.remaining() < data.len() {
44            return Err(EncodeError::BufferTooSmall);
45        }
46        let end = self.pos + data.len();
47        self.buf[self.pos..end].copy_from_slice(data);
48        self.pos = end;
49        Ok(())
50    }
51
52    /// Write a big-endian `u16`.
53    pub fn write_be_u16(&mut self, value: u16) -> 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(0x12).unwrap();
68        w.write_be_u16(0x3456).unwrap();
69        assert_eq!(w.as_written(), &[0x12, 0x34, 0x56]);
70    }
71
72    #[test]
73    fn writer_bounds() {
74        let mut buf = [0u8; 2];
75        let mut w = Writer::new(&mut buf);
76        w.write_be_u16(0x1234).unwrap();
77        assert_eq!(w.write_u8(0).unwrap_err(), EncodeError::BufferTooSmall);
78    }
79}