#![no_std]
#![allow(incomplete_features)]
#![feature(generic_const_exprs)]
mod test;
use core::mem::{self, MaybeUninit};
pub struct RingBuf<const SIZE_BITS: usize, T>
where
[(); 1 << SIZE_BITS]:,
{
read: usize,
write: usize,
size: usize,
data: [T; 1 << SIZE_BITS],
}
impl<const SIZE_BITS: usize, T> Default for RingBuf<SIZE_BITS, T>
where
[(); 1 << SIZE_BITS]:,
{
fn default() -> Self {
Self {
read: 0,
write: 0,
size: 0,
#[allow(clippy::uninit_assumed_init)]
data: unsafe { MaybeUninit::uninit().assume_init() },
}
}
}
impl<const SIZE_BITS: usize, T> RingBuf<SIZE_BITS, T>
where
[(); 1 << SIZE_BITS]:,
{
const MAX: usize = 1 << SIZE_BITS;
const MASK: usize = (1 << SIZE_BITS) - 1;
pub fn new() -> Self {
Self::default()
}
pub fn is_empty(&self) -> bool {
self.size == 0
}
pub fn is_full(&self) -> bool {
self.size == Self::MAX
}
pub fn push(&mut self, item: T) -> Result<(), T> {
if self.is_full() {
return Err(item);
}
self.data[self.write] = item;
self.size += 1;
self.write = (self.write + 1) & Self::MASK;
Ok(())
}
#[allow(clippy::result_unit_err)]
pub fn pop(&mut self) -> Result<T, ()> {
if self.is_empty() {
return Err(());
}
// Safety swapping uninitialized memory in the array is fine because
// blocks out of index are not accessible and the array is private.
#[allow(clippy::uninit_assumed_init)]
let mut result: T = unsafe { MaybeUninit::uninit().assume_init() };
// Using swap here because T is not required to be [Copy],
// so cannot use [mem::copy].
mem::swap(&mut result, &mut self.data[self.read]);
self.size -= 1;
self.read = (self.read + 1) & Self::MASK;
Ok(result)
}
}