#[derive(Clone)]
pub struct Buffer<T: Clone + Default> {
data: Box<[T]>,
}
impl<T: Clone + Default> Buffer<T> {
pub fn new(len: usize) -> Self {
Self {
data: vec![T::default(); len].into_boxed_slice(),
}
}
pub fn from_slice(slice: &[T]) -> Self {
Self {
data: slice.to_vec().into_boxed_slice(),
}
}
pub fn resize(&mut self, len: usize) {
self.data = vec![T::default(); len].into_boxed_slice();
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn as_slice(&self) -> &[T] {
&self.data
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
&mut self.data
}
}
impl<T: Clone + Default> std::ops::Deref for Buffer<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<T: Clone + Default> std::ops::DerefMut for Buffer<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}
impl<T: Clone + Default> Default for Buffer<T> {
fn default() -> Self {
Self::new(0)
}
}
#[derive(Clone)]
pub struct PushBuffer<T: Copy + Default> {
buffer: Box<[T]>,
index: usize,
}
impl<T: Copy + Default> PushBuffer<T> {
pub fn new(len: usize) -> Self {
Self {
buffer: vec![T::default(); len].into_boxed_slice(),
index: 0,
}
}
pub fn from_slice(slice: &[T]) -> Self {
Self {
buffer: slice.to_vec().into_boxed_slice(),
index: 0,
}
}
pub fn resize(&mut self, len: usize) {
self.buffer = vec![T::default(); len].into_boxed_slice();
self.index = 0;
}
#[inline]
pub fn push(&mut self, value: T) {
let len = self.buffer.len();
if len == 0 {
return;
}
if self.index < len {
let idx = self.index;
self.buffer[idx] = value;
self.index += 1;
} else {
self.buffer.copy_within(1..len, 0);
self.buffer[len - 1] = value;
}
}
pub fn get_index(&self) -> usize {
self.index
}
pub fn set_index(&mut self, index: usize) {
self.index = index.min(self.buffer.len());
}
pub fn len(&self) -> usize {
self.buffer.len()
}
pub fn is_empty(&self) -> bool {
self.buffer.is_empty()
}
}
impl<T: Copy + Default> std::ops::Deref for PushBuffer<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
&self.buffer
}
}
impl<T: Copy + Default> std::ops::DerefMut for PushBuffer<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.buffer
}
}
impl<T: Copy + Default> std::ops::Index<usize> for PushBuffer<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
&self.buffer[index]
}
}
impl<T: Copy + Default> std::ops::IndexMut<usize> for PushBuffer<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.buffer[index]
}
}
#[derive(Clone)]
pub struct CircularBuffer<T: Copy + Default> {
buffer: Box<[T]>,
read: usize,
write: usize,
mask: usize, }
impl<T: Copy + Default> CircularBuffer<T> {
pub fn new(len: usize) -> Self {
let actual_len = len.next_power_of_two().max(1);
Self {
buffer: vec![T::default(); actual_len].into_boxed_slice(),
read: 0,
write: 0,
mask: actual_len - 1,
}
}
pub fn from_slice(slice: &[T]) -> Self {
let len = slice.len().next_power_of_two().max(1);
let mut buffer = vec![T::default(); len];
buffer[..slice.len()].copy_from_slice(slice);
Self {
buffer: buffer.into_boxed_slice(),
read: 0,
write: slice.len() & (len - 1),
mask: len - 1,
}
}
pub fn resize(&mut self, len: usize) {
let actual_len = len.next_power_of_two().max(1);
self.buffer = vec![T::default(); actual_len].into_boxed_slice();
self.read = 0;
self.write = 0;
self.mask = actual_len - 1;
}
#[inline]
pub fn push(&mut self, value: T) {
let idx = self.write;
self.buffer[idx] = value;
self.write = (self.write + 1) & self.mask;
}
#[inline]
#[allow(clippy::should_implement_trait)]
pub fn next(&mut self) -> T {
let value = self.buffer[self.read];
self.read = (self.read + 1) & self.mask;
value
}
pub fn peek(&self) -> T {
self.buffer[self.read]
}
pub fn read_offset(&self, offset: usize) -> T {
self.buffer[(self.read + offset) & self.mask]
}
pub fn write_offset(&mut self, offset: usize, value: T) {
let idx = (self.write + offset) & self.mask;
self.buffer[idx] = value;
}
pub fn get_read(&self) -> usize {
self.read
}
pub fn get_write(&self) -> usize {
self.write
}
pub fn set_read(&mut self, index: usize) {
self.read = index & self.mask;
}
pub fn set_write(&mut self, index: usize) {
self.write = index & self.mask;
}
pub fn capacity(&self) -> usize {
self.buffer.len()
}
pub fn len(&self) -> usize {
self.mask + 1
}
pub fn is_empty(&self) -> bool {
self.capacity() == 0
}
pub fn clear(&mut self) {
self.buffer.fill(T::default());
self.read = 0;
self.write = 0;
}
}
impl<T: Copy + Default> std::ops::Deref for CircularBuffer<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
&self.buffer
}
}
impl<T: Copy + Default> std::ops::DerefMut for CircularBuffer<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.buffer
}
}
impl<T: Copy + Default> std::ops::Index<usize> for CircularBuffer<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
&self.buffer[index & self.mask]
}
}
impl<T: Copy + Default> std::ops::IndexMut<usize> for CircularBuffer<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
let idx = index & self.mask;
&mut self.buffer[idx]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_buffer_basic() {
let mut b = Buffer::<f32>::new(4);
assert_eq!(b.len(), 4);
b[0] = 1.0;
assert_eq!(b[0], 1.0);
b.resize(2);
assert_eq!(b.len(), 2);
}
#[test]
fn test_push_buffer_sliding_window() {
let mut history = PushBuffer::<f32>::new(4);
assert_eq!(&*history, &[0.0, 0.0, 0.0, 0.0]);
for x in [1.0, 2.0, 3.0] {
history.push(x);
}
assert_eq!(&*history, &[1.0, 2.0, 3.0, 0.0]);
history.push(4.0);
assert_eq!(&*history, &[1.0, 2.0, 3.0, 4.0]);
}
#[test]
fn test_circular_buffer_rounds_to_power_of_two() {
let cb = CircularBuffer::<f32>::new(100);
assert_eq!(cb.capacity(), 128);
}
#[test]
fn test_circular_buffer_delay() {
let mut cb = CircularBuffer::<f32>::new(4);
for i in 0..4 {
cb.push(i as f32);
}
assert_eq!(cb.next(), 0.0);
assert_eq!(cb.next(), 1.0);
}
}