88 lines
2.2 KiB
Rust
88 lines
2.2 KiB
Rust
use core::{
|
|
mem::MaybeUninit,
|
|
ops::{Index, IndexMut},
|
|
};
|
|
|
|
#[derive(Debug, Copy)]
|
|
pub struct CircularBuffer<T, const SIZE: usize> {
|
|
buffer: [MaybeUninit<T>; SIZE],
|
|
head: usize,
|
|
tail: usize,
|
|
len: usize,
|
|
}
|
|
|
|
impl<T: Copy, const SIZE: usize> Clone for CircularBuffer<T, SIZE> {
|
|
fn clone(&self) -> Self {
|
|
*self
|
|
}
|
|
}
|
|
|
|
impl<T, const SIZE: usize> CircularBuffer<T, SIZE> {
|
|
pub const fn new() -> Self {
|
|
Self {
|
|
buffer: [const { MaybeUninit::uninit() }; SIZE],
|
|
head: 0,
|
|
tail: 0,
|
|
len: 0,
|
|
}
|
|
}
|
|
|
|
pub fn len(&self) -> usize {
|
|
self.len
|
|
}
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
self.len() == 0
|
|
}
|
|
|
|
pub fn is_full(&self) -> bool {
|
|
self.len() == SIZE - 1
|
|
}
|
|
|
|
pub fn pop(&mut self) -> Option<T> {
|
|
if self.is_empty() {
|
|
None
|
|
} else {
|
|
let out = core::mem::replace(&mut self.buffer[self.head], MaybeUninit::uninit());
|
|
self.head = (self.head + 1) % SIZE;
|
|
self.len -= 1;
|
|
// # Safety
|
|
// the queue is not empty and head points to a valid value
|
|
Some(unsafe { out.assume_init() })
|
|
}
|
|
}
|
|
|
|
pub fn push(&mut self, value: T) -> bool {
|
|
self.buffer[self.tail] = MaybeUninit::new(value);
|
|
self.tail = (self.tail + 1) % SIZE;
|
|
if self.is_full() {
|
|
self.head = (self.head + 1) % SIZE;
|
|
true
|
|
} else {
|
|
self.len += 1;
|
|
false
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T, const SIZE: usize> Index<usize> for CircularBuffer<T, SIZE> {
|
|
type Output = T;
|
|
|
|
fn index(&self, index: usize) -> &Self::Output {
|
|
if self.len() > index {
|
|
unsafe { self.buffer[(self.head + index) % SIZE].assume_init_ref() }
|
|
} else {
|
|
panic!("index is bigger than circular buffer")
|
|
}
|
|
}
|
|
}
|
|
impl<T, const SIZE: usize> IndexMut<usize> for CircularBuffer<T, SIZE> {
|
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
|
if self.len() > index {
|
|
unsafe { self.buffer[(self.head + index) % SIZE].assume_init_mut() }
|
|
} else {
|
|
panic!("index is bigger than circular buffer")
|
|
}
|
|
}
|
|
}
|