1pub trait IoWrite {
2 type Error: core::error::Error;
3 fn write_byte(&mut self, byte: u8) -> Result<(), Self::Error>;
4 fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
5 for byte in buf {
6 self.write_byte(*byte)?;
7 }
8
9 Ok(())
10 }
11}
12
13#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
15pub enum WError {
16 BufferFull,
18}
19
20impl core::fmt::Display for WError {
21 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
22 match self {
23 WError::BufferFull => write!(f, "Buffer is full"),
24 }
25 }
26}
27
28impl core::error::Error for WError {}
29
30pub struct SliceWriter<'a> {
31 buf: &'a mut [u8],
32 cursor: usize,
33}
34
35impl<'a> SliceWriter<'a> {
36 pub fn from_slice(buf: &'a mut [u8]) -> Self {
37 Self { buf, cursor: 0 }
38 }
39
40 fn len(&self) -> usize {
41 self.buf.len() - self.cursor
42 }
43}
44
45impl IoWrite for SliceWriter<'_> {
46 type Error = WError;
47
48 fn write_byte(&mut self, byte: u8) -> Result<(), Self::Error> {
49 if self.len() >= 1 {
50 self.buf[self.cursor] = byte;
51 self.cursor += 1;
52 Ok(())
53 } else {
54 Err(WError::BufferFull)
55 }
56 }
57
58 fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
59 if self.len() >= buf.len() {
60 let to = &mut self.buf[self.cursor..self.cursor + buf.len()];
61 to.copy_from_slice(buf);
62 self.cursor += buf.len();
63 Ok(())
64 } else {
65 Err(WError::BufferFull)
66 }
67 }
68}
69
70#[cfg(any(test, feature = "std"))]
71impl<W> IoWrite for W
72where
73 W: std::io::Write,
74{
75 type Error = std::io::Error;
76
77 fn write_byte(&mut self, byte: u8) -> Result<(), Self::Error> {
78 match self.write_all(&[byte]) {
79 Ok(_) => Ok(()),
80 Err(e) => Err(e),
81 }
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 #[should_panic]
91 fn buffer_full() {
92 let buf: &mut [u8] = &mut [0u8];
93 let mut writer = SliceWriter::from_slice(buf);
94 writer.write_bytes(&[1, 2]).unwrap();
95 }
96}