use std::io::{Read, Result as IOResult}; pub struct NotEnoughSpace; pub struct Buf { written_len: usize, data: T, _dt: core::marker::PhantomData, } impl Buf { pub fn new(data: T) -> Self { Self { data, written_len: 0, _dt: Default::default(), } } } impl Buf where T: AsRef<[U]>, { pub fn remaining(&self) -> &[U] { &self.data.as_ref()[self.written_len..] } pub fn filled(&self) -> &[U] { &self.data.as_ref()[..self.written_len] } } impl Buf where T: AsRef<[U]>, T: AsMut<[U]>, { pub fn remaining_mut(&mut self) -> &mut [U] { &mut self.data.as_mut()[self.written_len..] } pub fn extend_from_slice(&mut self, s: &[U]) -> Result<(), NotEnoughSpace> where U: Copy, { if self.remaining().len() < s.len() { return Err(NotEnoughSpace); } self.remaining_mut()[..s.len()].copy_from_slice(s); self.written_len += s.len(); Ok(()) } pub fn clear(&mut self) { self.written_len = 0; } pub fn pop_front_alloc(&mut self, amt: usize) where U: Copy + Default, { let to_copy = &self.filled()[amt..]; let buf_sz = to_copy.len(); let mut buf = vec![Default::default(); buf_sz].into_boxed_slice(); buf.copy_from_slice(to_copy); self.clear(); let _ = self.extend_from_slice(&buf); } pub fn pop_front(&mut self, amt: usize) where U: Copy, { if amt > self.filled().len() { panic!("Filled not big enough"); } let data = self.data.as_mut(); let src = &data[amt..]; let count = data.len() - amt; // SAFETY: // - src comes from data // - U is copy // - count is within bounds of data unsafe { core::ptr::copy(src.as_ptr(), data.as_mut_ptr(), count) } self.written_len -= amt; } } impl Buf where T: AsRef<[u8]> + AsMut<[u8]>, { pub fn read_from(&mut self, mut r: impl Read) -> IOResult { let remaining = self.remaining_mut(); let amt = r.read(remaining)?; self.written_len += amt; Ok(amt) } } impl httplz::Write for Buf where T: AsRef<[u8]> + AsMut<[u8]>, { fn write(&mut self, buf: &[u8]) -> httplz::Written { self.extend_from_slice(buf) .map_err(|_| httplz::ErrorKind::BufNotBigEnough.into()) } }