use std::iter;
pub struct CircularBuffer<T> {
buffer: Vec<T>,
next_write_pos: usize,
}
#[allow(dead_code)]
impl<T> CircularBuffer<T> {
pub fn new(max_depth: usize) -> CircularBuffer<T> {
CircularBuffer {
buffer: Vec::with_capacity(max_depth),
next_write_pos: 0,
}
}
pub fn len(&self) -> usize {
self.buffer.len()
}
pub fn is_empty(&self) -> bool {
self.buffer.is_empty()
}
pub fn capacity(&self) -> usize {
self.buffer.capacity()
}
pub fn push(&mut self, elem: T) {
let max_depth = self.buffer.capacity();
if self.buffer.len() < max_depth {
self.buffer.push(elem);
} else {
self.buffer[self.next_write_pos % max_depth] = elem;
}
self.next_write_pos += 1;
}
pub fn take(&mut self) -> Vec<T> {
let mut consumed = vec![];
let max_depth = self.buffer.capacity();
if self.buffer.len() < max_depth {
consumed.append(&mut self.buffer);
} else {
let pos = self.next_write_pos % max_depth;
let mut xvec = self.buffer.split_off(pos);
consumed.append(&mut xvec);
consumed.append(&mut self.buffer)
}
self.next_write_pos = 0;
consumed
}
pub fn total_elements(&self) -> usize {
self.next_write_pos
}
pub fn has_wrapped(&self) -> bool {
self.next_write_pos > self.buffer.capacity()
}
pub fn iter(&mut self) -> iter::Chain<std::slice::Iter<T>, std::slice::Iter<T>> {
let max_depth = self.buffer.capacity();
if self.next_write_pos <= max_depth {
self.buffer.iter().chain(self.buffer[..0].iter())
} else {
let wrap = self.next_write_pos % max_depth;
let it_end = self.buffer[..wrap].iter();
let it_start = self.buffer[wrap..].iter();
it_start.chain(it_end)
}
}
pub fn rev_iter(
&mut self,
) -> iter::Chain<std::iter::Rev<std::slice::Iter<T>>, std::iter::Rev<std::slice::Iter<T>>> {
let max_depth = self.buffer.capacity();
if self.next_write_pos <= max_depth {
self.buffer
.iter()
.rev()
.chain(self.buffer[..0].iter().rev())
} else {
let wrap = self.next_write_pos % max_depth;
let it_end = self.buffer[..wrap].iter().rev();
let it_start = self.buffer[wrap..].iter().rev();
it_end.chain(it_start)
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn circular_buffer() {
use crate::CircularBuffer;
let mut cb: CircularBuffer<u64> = CircularBuffer::new(5);
{
let mut cb_iter = cb.iter();
assert_eq!(cb_iter.next(), None);
}
cb.push(1);
{
let mut cb_iter = cb.iter();
assert_eq!(cb_iter.next(), Some(&1));
assert_eq!(cb_iter.next(), None);
}
cb.push(2);
{
let mut cb_iter = cb.iter();
assert_eq!(cb_iter.next(), Some(&1));
assert_eq!(cb_iter.next(), Some(&2));
assert_eq!(cb_iter.next(), None);
}
cb.push(3);
{
let mut cb_iter = cb.iter();
assert_eq!(cb_iter.next(), Some(&1));
assert_eq!(cb_iter.next(), Some(&2));
assert_eq!(cb_iter.next(), Some(&3));
assert_eq!(cb_iter.next(), None);
}
cb.push(4);
{
let mut cb_iter = cb.iter();
assert_eq!(cb_iter.next(), Some(&1));
assert_eq!(cb_iter.next(), Some(&2));
assert_eq!(cb_iter.next(), Some(&3));
assert_eq!(cb_iter.next(), Some(&4));
assert_eq!(cb_iter.next(), None);
}
cb.push(5);
{
let mut cb_iter = cb.iter();
assert_eq!(cb_iter.next(), Some(&1));
assert_eq!(cb_iter.next(), Some(&2));
assert_eq!(cb_iter.next(), Some(&3));
assert_eq!(cb_iter.next(), Some(&4));
assert_eq!(cb_iter.next(), Some(&5));
assert_eq!(cb_iter.next(), None);
}
cb.push(6);
{
let mut cb_iter = cb.iter();
assert_eq!(cb_iter.next(), Some(&2));
assert_eq!(cb_iter.next(), Some(&3));
assert_eq!(cb_iter.next(), Some(&4));
assert_eq!(cb_iter.next(), Some(&5));
assert_eq!(cb_iter.next(), Some(&6));
assert_eq!(cb_iter.next(), None);
}
cb.push(7);
{
let mut cb_iter = cb.iter();
assert_eq!(cb_iter.next(), Some(&3));
assert_eq!(cb_iter.next(), Some(&4));
assert_eq!(cb_iter.next(), Some(&5));
assert_eq!(cb_iter.next(), Some(&6));
assert_eq!(cb_iter.next(), Some(&7));
assert_eq!(cb_iter.next(), None);
}
cb.push(8);
{
let mut cb_iter = cb.iter();
assert_eq!(cb_iter.next(), Some(&4));
assert_eq!(cb_iter.next(), Some(&5));
assert_eq!(cb_iter.next(), Some(&6));
assert_eq!(cb_iter.next(), Some(&7));
assert_eq!(cb_iter.next(), Some(&8));
assert_eq!(cb_iter.next(), None);
}
cb.push(9);
{
let mut cb_iter = cb.iter();
assert_eq!(cb_iter.next(), Some(&5));
assert_eq!(cb_iter.next(), Some(&6));
assert_eq!(cb_iter.next(), Some(&7));
assert_eq!(cb_iter.next(), Some(&8));
assert_eq!(cb_iter.next(), Some(&9));
assert_eq!(cb_iter.next(), None);
}
cb.push(10);
{
let mut cb_iter = cb.iter();
assert_eq!(cb_iter.next(), Some(&6));
assert_eq!(cb_iter.next(), Some(&7));
assert_eq!(cb_iter.next(), Some(&8));
assert_eq!(cb_iter.next(), Some(&9));
assert_eq!(cb_iter.next(), Some(&10));
assert_eq!(cb_iter.next(), None);
}
cb.push(11);
{
let mut cb_iter = cb.iter();
assert_eq!(cb_iter.next(), Some(&7));
assert_eq!(cb_iter.next(), Some(&8));
assert_eq!(cb_iter.next(), Some(&9));
assert_eq!(cb_iter.next(), Some(&10));
assert_eq!(cb_iter.next(), Some(&11));
assert_eq!(cb_iter.next(), None);
}
}
#[test]
fn circular_buffer_rev() {
use crate::CircularBuffer;
let mut cb: CircularBuffer<u64> = CircularBuffer::new(5);
{
let mut cb_iter = cb.rev_iter();
assert_eq!(cb_iter.next(), None);
}
cb.push(1);
{
let mut cb_iter = cb.rev_iter();
assert_eq!(cb_iter.next(), Some(&1));
assert_eq!(cb_iter.next(), None);
}
cb.push(2);
{
let mut cb_iter = cb.rev_iter();
assert_eq!(cb_iter.next(), Some(&2));
assert_eq!(cb_iter.next(), Some(&1));
assert_eq!(cb_iter.next(), None);
}
cb.push(3);
{
let mut cb_iter = cb.rev_iter();
assert_eq!(cb_iter.next(), Some(&3));
assert_eq!(cb_iter.next(), Some(&2));
assert_eq!(cb_iter.next(), Some(&1));
assert_eq!(cb_iter.next(), None);
}
cb.push(4);
{
let mut cb_iter = cb.rev_iter();
assert_eq!(cb_iter.next(), Some(&4));
assert_eq!(cb_iter.next(), Some(&3));
assert_eq!(cb_iter.next(), Some(&2));
assert_eq!(cb_iter.next(), Some(&1));
assert_eq!(cb_iter.next(), None);
}
cb.push(5);
{
let mut cb_iter = cb.rev_iter();
assert_eq!(cb_iter.next(), Some(&5));
assert_eq!(cb_iter.next(), Some(&4));
assert_eq!(cb_iter.next(), Some(&3));
assert_eq!(cb_iter.next(), Some(&2));
assert_eq!(cb_iter.next(), Some(&1));
assert_eq!(cb_iter.next(), None);
}
cb.push(6);
{
let mut cb_iter = cb.rev_iter();
assert_eq!(cb_iter.next(), Some(&6));
assert_eq!(cb_iter.next(), Some(&5));
assert_eq!(cb_iter.next(), Some(&4));
assert_eq!(cb_iter.next(), Some(&3));
assert_eq!(cb_iter.next(), Some(&2));
assert_eq!(cb_iter.next(), None);
}
cb.push(7);
{
let mut cb_iter = cb.rev_iter();
assert_eq!(cb_iter.next(), Some(&7));
assert_eq!(cb_iter.next(), Some(&6));
assert_eq!(cb_iter.next(), Some(&5));
assert_eq!(cb_iter.next(), Some(&4));
assert_eq!(cb_iter.next(), Some(&3));
assert_eq!(cb_iter.next(), None);
}
cb.push(8);
{
let mut cb_iter = cb.rev_iter();
assert_eq!(cb_iter.next(), Some(&8));
assert_eq!(cb_iter.next(), Some(&7));
assert_eq!(cb_iter.next(), Some(&6));
assert_eq!(cb_iter.next(), Some(&5));
assert_eq!(cb_iter.next(), Some(&4));
assert_eq!(cb_iter.next(), None);
}
cb.push(9);
{
let mut cb_iter = cb.rev_iter();
assert_eq!(cb_iter.next(), Some(&9));
assert_eq!(cb_iter.next(), Some(&8));
assert_eq!(cb_iter.next(), Some(&7));
assert_eq!(cb_iter.next(), Some(&6));
assert_eq!(cb_iter.next(), Some(&5));
assert_eq!(cb_iter.next(), None);
}
cb.push(10);
{
let mut cb_iter = cb.rev_iter();
assert_eq!(cb_iter.next(), Some(&10));
assert_eq!(cb_iter.next(), Some(&9));
assert_eq!(cb_iter.next(), Some(&8));
assert_eq!(cb_iter.next(), Some(&7));
assert_eq!(cb_iter.next(), Some(&6));
assert_eq!(cb_iter.next(), None);
}
cb.push(11);
{
let mut cb_iter = cb.rev_iter();
assert_eq!(cb_iter.next(), Some(&11));
assert_eq!(cb_iter.next(), Some(&10));
assert_eq!(cb_iter.next(), Some(&9));
assert_eq!(cb_iter.next(), Some(&8));
assert_eq!(cb_iter.next(), Some(&7));
assert_eq!(cb_iter.next(), None);
}
}
#[test]
fn total_elements() {
use crate::CircularBuffer;
let mut cb: CircularBuffer<u64> = CircularBuffer::new(5);
assert_eq!(0, cb.total_elements());
for i in 1..20 {
cb.push(i);
assert_eq!(i as usize, cb.total_elements());
}
}
#[test]
fn has_wrapped() {
use crate::CircularBuffer;
let mut cb: CircularBuffer<u64> = CircularBuffer::new(5);
assert_eq!(0, cb.total_elements());
for i in 1..20 {
cb.push(i);
assert_eq!(i >= 6, cb.has_wrapped());
}
}
#[test]
fn take() {
use crate::CircularBuffer;
let mut cb: CircularBuffer<u64> = CircularBuffer::new(5);
for i in 1..5 {
cb.push(i);
}
assert_eq!(vec![1, 2, 3, 4], cb.take());
for i in 1..6 {
cb.push(i);
}
assert_eq!(vec![1, 2, 3, 4, 5], cb.take());
for i in 1..7 {
cb.push(i);
}
assert_eq!(vec![2, 3, 4, 5, 6], cb.take());
let mut cb: CircularBuffer<u64> = CircularBuffer::new(5);
for i in 1..20 {
cb.push(i);
}
assert_eq!(vec![15, 16, 17, 18, 19], cb.take());
}
}