#![no_std]
#[derive(Debug)]
pub enum RingBufferError {
Full,
BeyondRange,
BufferIncomplete,
}
pub struct RingBuffer<T, const S: usize>
where
T: Default + Copy,
{
buffer: [T; S],
head: usize,
tail: usize,
len: usize,
}
impl<T, const S: usize> RingBuffer<T, S>
where
T: Default + Copy,
{
pub fn new() -> Self {
RingBuffer {
buffer: [T::default(); S],
head: 0,
tail: 0,
len: 0,
}
}
pub fn push(&mut self, item: T) -> Result<(), RingBufferError> {
if self.len == S {
return Err(RingBufferError::Full);
}
self.buffer[self.head] = item;
self.head = (self.head + 1) % S;
self.len += 1;
Ok(())
}
pub fn pop(&mut self) -> Option<T> {
if self.len == 0 {
return None;
}
let item = self.buffer[self.tail];
self.tail = (self.tail + 1) % S;
self.len -= 1;
Some(item)
}
pub fn clear(&mut self) {
self.head = 0;
self.tail = 0;
self.len = 0;
}
pub fn pop_continuous(&mut self, count: usize) -> Result<usize, RingBufferError> {
if count > self.len {
return Result::Err(RingBufferError::BeyondRange);
}
self.tail = (self.tail + count) % S;
self.len -= count;
Ok(self.remaining_capacity())
}
#[inline]
pub fn capacity(&self) -> usize {
S
}
#[inline]
pub fn remaining_capacity(&self) -> usize {
S - self.len
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn is_full(&self) -> bool {
self.len == S
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
pub fn write(&mut self, data: &[T]) -> Result<(), RingBufferError> {
for &item in data {
self.push(item)?;
}
Ok(())
}
pub fn read(&mut self, buffer: &mut [T]) -> usize {
for i in 0..buffer.len() {
if let Some(item) = self.pop() {
buffer[i] = item;
} else {
return i;
}
}
buffer.len()
}
pub fn read_slice(&self, len: usize) -> Result<&[T], RingBufferError> {
if len > self.len {
return Err(RingBufferError::BeyondRange);
}
if self.tail < self.head {
Ok(&self.buffer[self.tail..self.tail + len])
} else if self.tail + len <= S {
Ok(&self.buffer[self.tail..self.tail + len])
} else {
Err(RingBufferError::BufferIncomplete)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
const SIZE: usize = 4096; let mut rb: RingBuffer<u32, SIZE> = RingBuffer::new();
assert!(rb.is_empty());
assert!(!rb.is_full());
for i in 0..SIZE {
rb.push(i as u32).unwrap();
}
assert_eq!(rb.len(), SIZE);
assert!(!rb.is_empty());
assert!(rb.is_full());
let mut buffer = [0; 5];
let read_count = rb.read(&mut buffer);
assert_eq!(read_count, 5);
assert_eq!(&buffer[..5], &[0, 1, 2, 3, 4]);
let read_count = rb.read(&mut buffer);
assert_eq!(read_count, 5);
assert_eq!(&buffer[..5], &[5, 6, 7, 8, 9]);
assert_eq!(rb.len(), SIZE - 10);
assert!(!rb.is_full());
assert!(!rb.is_empty());
assert_eq!(rb.remaining_capacity(), SIZE - rb.len());
rb.clear();
assert!(rb.is_empty());
for i in 0..SIZE {
rb.push(i as u32).unwrap();
}
let slice = rb.read_slice(10).unwrap();
assert_eq!(rb.len(), SIZE);
assert_eq!(slice, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
let remaining_capacity = rb.pop_continuous(10).unwrap();
assert_eq!(remaining_capacity, 10);
assert_eq!(rb.len(), SIZE - 10);
let slice = rb.read_slice(10).unwrap();
assert_eq!(slice, &[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]);
assert_eq!(rb.len(), SIZE - 10);
for _ in 0..rb.len() {
rb.pop();
}
assert!(rb.is_empty());
assert_eq!(size_of::<RingBuffer<u8, 1>>(), 32);
assert_eq!(size_of::<RingBuffer<u8, 2>>(), 32);
assert_eq!(size_of::<RingBuffer<u8, 4>>(), 32);
assert_eq!(size_of::<RingBuffer<u8, 8>>(), 32);
assert_eq!(size_of::<RingBuffer<u8, 16>>(), 40);
assert_eq!(size_of::<RingBuffer<u8, 32>>(), 56);
assert_eq!(size_of::<RingBuffer<u8, 64>>(), 88);
assert_eq!(size_of::<RingBuffer<u8, 128>>(), 152);
assert_eq!(size_of::<RingBuffer<u8, 256>>(), 280);
assert_eq!(size_of::<RingBuffer<u8, 512>>(), 536);
assert_eq!(size_of::<RingBuffer<u8, 1024>>(), 1048);
assert_eq!(size_of::<RingBuffer<u8, 4096>>(), 4120);
assert_eq!(size_of::<RingBuffer<u8, 10>>(), 40); }
}