1use std::io;
2
3pub struct BufCfg<D: Into<Vec<u8>>> {
4 initial_data: D,
5 min_capacity: usize,
6}
7
8impl BufCfg<[u8; 0]> {
9 pub fn with_capacity(capacity: usize) -> Self {
11 Self {
12 initial_data: [],
13 min_capacity: capacity,
14 }
15 }
16}
17
18impl<D: Into<Vec<u8>>> BufCfg<D> {
19 pub fn with_data(initial_data: D, min_capacity: usize) -> Self {
22 Self {
23 initial_data,
24 min_capacity,
25 }
26 }
27}
28
29pub struct Buffer {
30 buf: Box<[u8]>,
31 start: usize,
32 end: usize,
33}
34
35impl Buffer {
36 pub fn build_from<D: Into<Vec<u8>>>(cfg: BufCfg<D>) -> Self {
37 let mut buf: Vec<u8> = cfg.initial_data.into();
38 let end = buf.len();
39
40 if buf.len() < cfg.min_capacity {
41 buf.resize(cfg.min_capacity, 0u8);
43 }
44
45 assert_ne!(buf.len(), 0); let buf = buf.into_boxed_slice();
48
49 Self { buf, start: 0, end }
50 }
51
52 pub fn read_from(&mut self, reader: &mut impl io::Read) -> io::Result<usize> {
53 let bytes_read = reader.read(&mut self.buf[self.end..])?;
54 self.end += bytes_read;
55 Ok(bytes_read)
56 }
57
58 pub fn write_to(&mut self, writer: &mut impl io::Write) -> io::Result<usize> {
59 let bytes_written = writer.write(&self.buf[self.start..self.end])?;
60 self.start += bytes_written;
61 self.check_start();
62 Ok(bytes_written)
63 }
64
65 pub fn is_empty(&self) -> bool {
66 self.end == 0
67 }
68
69 pub fn is_full(&self) -> bool {
70 self.end == self.buf.len()
71 }
72
73 fn check_start(&mut self) {
74 if self.start == self.end {
75 self.start = 0;
76 self.end = 0;
77 }
78 }
79}
80
81impl io::Read for Buffer {
82 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
83 let src = &self.buf[self.start..self.end];
84 let len = std::cmp::min(src.len(), buf.len());
85 buf[..len].copy_from_slice(&src[..len]);
86 self.start += len;
87 self.check_start();
88 Ok(len)
89 }
90}
91
92impl io::Write for Buffer {
93 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
94 let dst = &mut self.buf[self.end..];
95 let len = std::cmp::min(dst.len(), buf.len());
96 dst[..len].copy_from_slice(&buf[..len]);
97 self.end += len;
98 Ok(len)
99 }
100
101 fn flush(&mut self) -> io::Result<()> {
102 Err(io::ErrorKind::InvalidInput.into())
103 }
104}