use core::ops::{Deref, DerefMut}; #[derive(Debug)] pub struct BufferOverflow; #[derive(Debug)] pub struct Buffer<'a, const N: usize, T = u8> { data: &'a mut [T; N], i: usize, } impl<'a, const N: usize, T: Copy> Buffer<'a, N, T> { /// Constructs a new `Buffer`. /// `data` is the backing array. /// `i` is the number of elements in `data` that contain data (and should thus be exposed by `Buffer`) pub fn new(data: &'a mut [T; N], i: usize) -> Self { assert!(i <= data.len()); Self { data, i } } pub fn new_full(data: &'a mut [T; N]) -> Self { let i = data.len(); Self::new(data, i) } pub fn new_empty(data: &'a mut [T; N]) -> Self { Self::new(data, 0) } pub const fn remaining_capacity(&self) -> usize { N - self.i } pub fn try_push(&mut self, v: T) -> Result<(), BufferOverflow> { if self.i == N { return Err(BufferOverflow); } self.data[self.i] = v; self.i += 1; Ok(()) } pub fn push(&mut self, v: T) { self.try_push(v).unwrap(); } pub fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), BufferOverflow> { if self.remaining_capacity() < other.len() { return Err(BufferOverflow); } self.data[self.i..(self.i + other.len())].copy_from_slice(other); self.i += other.len(); Ok(()) } pub fn extend(&mut self, other: &[T]) { self.try_extend_from_slice(other).unwrap(); } pub fn pop(&mut self) -> Option<T> { if self.i == 0 { return None; } self.i -= 1; Some(self.data[self.i]) } pub fn truncate(&mut self, new_len: usize) { assert!(self.i >= new_len); self.i = new_len; } pub fn drain(&mut self, start: usize, end: usize) { assert!(end >= start); assert!(end <= self.i); let delta = end - start; let surplus = self.len() - end; for i in start..(start + surplus) { self[i] = self[i + delta]; } self.i -= delta; } pub fn clone_backing<'b>(&self, buf: &'b mut [T; N]) -> Buffer<'b, N, T> { let mut out = Buffer::new_empty(buf); out.extend(self); out } } impl<'a, const N: usize, T> From<&'a mut [T; N]> for Buffer<'a, N, T> { fn from(data: &'a mut [T; N]) -> Self { Self { data, i: 0 } } } impl<const N: usize, T> Deref for Buffer<'_, N, T> { type Target = [T]; fn deref(&self) -> &Self::Target { &self.data[..self.i] } } impl<const N: usize, T> DerefMut for Buffer<'_, N, T> { fn deref_mut(&mut self) -> &mut [T] { &mut self.data[..self.i] } }