1use std::io::{Read, Result as IOResult};
2
3pub struct NotEnoughSpace;
4pub struct Buf<T, U> {
5 written_len: usize,
6 data: T,
7 _dt: core::marker::PhantomData<U>,
8}
9impl<T, U> Buf<T, U> {
10 pub fn new(data: T) -> Self {
11 Self {
12 data,
13 written_len: 0,
14 _dt: Default::default(),
15 }
16 }
17}
18
19impl<T, U> Buf<T, U>
20where
21 T: AsRef<[U]>,
22{
23 pub fn remaining(&self) -> &[U] {
24 &self.data.as_ref()[self.written_len..]
25 }
26
27 pub fn filled(&self) -> &[U] {
28 &self.data.as_ref()[..self.written_len]
29 }
30}
31
32impl<T, U> Buf<T, U>
33where
34 T: AsRef<[U]>,
35 T: AsMut<[U]>,
36{
37 pub fn remaining_mut(&mut self) -> &mut [U] {
38 &mut self.data.as_mut()[self.written_len..]
39 }
40
41 pub fn extend_from_slice(&mut self, s: &[U]) -> Result<(), NotEnoughSpace>
42 where
43 U: Copy,
44 {
45 if self.remaining().len() < s.len() {
46 return Err(NotEnoughSpace);
47 }
48
49 self.remaining_mut()[..s.len()].copy_from_slice(s);
50 self.written_len += s.len();
51
52 Ok(())
53 }
54
55 pub fn clear(&mut self) {
56 self.written_len = 0;
57 }
58
59 pub fn pop_front_alloc(&mut self, amt: usize)
60 where
61 U: Copy + Default,
62 {
63 let to_copy = &self.filled()[amt..];
64 let buf_sz = to_copy.len();
65 let mut buf = vec![Default::default(); buf_sz].into_boxed_slice();
66 buf.copy_from_slice(to_copy);
67 self.clear();
68 let _ = self.extend_from_slice(&buf);
69 }
70
71 pub fn pop_front(&mut self, amt: usize)
72 where
73 U: Copy,
74 {
75 if amt > self.filled().len() {
76 panic!("Filled not big enough");
77 }
78
79 let data = self.data.as_mut();
80
81 let src = &data[amt..];
82 let count = data.len() - amt;
83
84 unsafe { core::ptr::copy(src.as_ptr(), data.as_mut_ptr(), count) }
89
90 self.written_len -= amt;
91 }
92}
93
94impl<T> Buf<T, u8>
95where
96 T: AsRef<[u8]> + AsMut<[u8]>,
97{
98 pub fn read_from(&mut self, mut r: impl Read) -> IOResult<usize> {
99 let remaining = self.remaining_mut();
100 let amt = r.read(remaining)?;
101
102 self.written_len += amt;
103
104 Ok(amt)
105 }
106}
107
108impl<T> httplz::Write for Buf<T, u8>
109where
110 T: AsRef<[u8]> + AsMut<[u8]>,
111{
112 fn write(&mut self, buf: &[u8]) -> httplz::Written {
113 self.extend_from_slice(buf)
114 .map_err(|_| httplz::ErrorKind::BufNotBigEnough.into())
115 }
116}