use crate::Barfer;
use core::mem::MaybeUninit;
pub struct StackBuffer<T: Sized, const N: usize> {
pub(crate) buffer: [MaybeUninit<T>; N],
pub(crate) len: usize,
}
impl<T, const N: usize> Clone for StackBuffer<T, N>
where
MaybeUninit<T>: Clone,
{
fn clone(&self) -> Self {
Self {
buffer: self.buffer.clone(),
len: self.len,
}
}
}
impl<T: Copy, const N: usize> Copy for StackBuffer<T, N> {}
#[derive(Debug, PartialEq)]
pub enum StackBufferError {
NotEnoughCapacity,
}
impl<T, const N: usize> StackBuffer<T, N> {
#[inline]
pub fn new() -> Self {
StackBuffer {
buffer: unsafe { MaybeUninit::uninit().assume_init() },
len: 0,
}
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn push(&mut self, value: T) -> Result<(), StackBufferError> {
if self.len >= N {
return Err(StackBufferError::NotEnoughCapacity);
}
self.buffer[self.len].write(value);
self.len += 1;
Ok(())
}
pub fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) -> Result<(), StackBufferError> {
let initial_len = self.len;
let values = iter.into_iter();
for value in values.into_iter() {
if self.len >= N {
self.len = initial_len;
return Err(StackBufferError::NotEnoughCapacity);
}
self.buffer[self.len].write(value);
self.len += 1;
}
Ok(())
}
pub fn extend_from_slice<S: AsRef<[T]>>(&mut self, slice: S) -> Result<(), StackBufferError>
where
T: Clone,
{
let values = slice.as_ref();
if self.len + values.len() > N {
return Err(StackBufferError::NotEnoughCapacity);
}
for value in values.iter() {
self.buffer[self.len].write(value.clone());
self.len += 1;
}
Ok(())
}
#[inline]
pub fn get(&self) -> &[T] {
unsafe { &*(&self.buffer[..self.len] as *const [MaybeUninit<T>] as *const [T]) }
}
}
impl<T, const N: usize> Default for StackBuffer<T, N> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<T, const N: usize> Barfer<T> for StackBuffer<T, N> {
type Error = StackBufferError;
#[inline]
fn single(&mut self, value: T) -> Result<(), Self::Error> {
self.push(value)
}
#[inline]
fn many<I: IntoIterator<Item = T>>(&mut self, iter: I) -> Result<(), Self::Error> {
self.extend(iter)
}
#[inline]
fn slice<S: AsRef<[T]>>(&mut self, slice: S) -> Result<(), Self::Error>
where
T: Clone,
{
self.extend_from_slice(slice)
}
}