use std::fmt::Debug;
use super::RingBuffer;
use crate::{len, Index, Length};
#[derive(Clone, Debug, PartialEq)]
pub struct RingBufferHeap<T, const N: usize> {
internal_storage: Vec<Option<T>>,
head: usize,
tail: usize,
count: usize,
}
impl<T, const N: usize> Default for RingBufferHeap<T, N> {
fn default() -> Self { Self::new() }
}
impl<T, const N: usize> RingBufferHeap<T, N> {
pub fn new() -> Self {
RingBufferHeap {
internal_storage: Vec::with_capacity(N),
head: 0,
tail: 0,
count: 0,
}
}
}
impl<T, const N: usize> RingBuffer<T, N> for RingBufferHeap<T, N> {
fn clear(&mut self) {
self.head = 0;
self.tail = 0;
self.count = 0;
self.internal_storage.iter_mut().for_each(|x| *x = None);
}
fn get(&self, index_arg: impl Into<Index>) -> Option<&T> {
let index = {
let it: Index = index_arg.into();
it.as_usize()
};
if index >= self.count {
return None;
}
let actual_index = (self.tail + index) % N;
self.internal_storage
.get(actual_index)
.and_then(|item| item.as_ref())
}
fn len(&self) -> Length { len(self.count) }
fn add(&mut self, value: T) {
if self.count == N {
let _ = self.remove(); }
if self.internal_storage.len() < N {
self.internal_storage.push(Some(value));
} else {
self.internal_storage[self.head] = Some(value);
}
self.head = (self.head + 1) % N;
self.count = std::cmp::min(self.count + 1, N); }
fn remove(&mut self) -> Option<T> {
if self.count == 0 {
return None;
}
if self.internal_storage.is_empty() {
return None;
}
let value = self.internal_storage[self.tail].take();
self.tail = (self.tail + 1) % N;
self.count -= 1;
value
}
fn remove_head(&mut self) -> Option<T> {
if self.count == 0 {
return None;
}
if self.internal_storage.is_empty() {
return None;
}
self.head = (self.head + N - 1) % N;
let value = self.internal_storage[self.head].take();
self.count -= 1;
value
}
fn truncate(&mut self, arg_index: impl Into<Index>) {
let index = {
let it: Index = arg_index.into();
it.as_usize()
};
if index >= self.count {
return;
}
let actual_index = (self.tail + index) % N;
for i in 0..N {
let wrapped_index = (actual_index + i) % N;
if i < self.count - index {
self.internal_storage[wrapped_index] = None;
} else {
break;
}
}
self.head = actual_index;
self.count = index;
}
fn as_slice_raw(&self) -> &[Option<T>] { &self.internal_storage }
}
impl<T, const N: usize> RingBufferHeap<T, N> {
pub fn iter(&self) -> RingBufferHeapIterator<'_, T, N> {
RingBufferHeapIterator {
ring_buffer: self,
iterator_index: 0,
}
}
}
pub struct RingBufferHeapIterator<'a, T, const N: usize> {
ring_buffer: &'a RingBufferHeap<T, N>,
iterator_index: usize,
}
impl<'a, T, const N: usize> Iterator for RingBufferHeapIterator<'a, T, N> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.iterator_index == self.ring_buffer.count {
return None;
}
let actual_index = (self.ring_buffer.tail + self.iterator_index) % N;
self.iterator_index += 1;
self.ring_buffer
.internal_storage
.get(actual_index)
.and_then(|x| x.as_ref())
}
}
#[cfg(test)]
mod tests {
use smallstr::SmallString;
use super::*;
use crate::len;
pub type SmallStringBackingStore = SmallString<[u8; DEFAULT_SMALL_STRING_SIZE]>;
pub const DEFAULT_SMALL_STRING_SIZE: usize = 32;
#[test]
fn test_empty_ring_buffer_heap() {
let ring_buffer: RingBufferHeap<SmallStringBackingStore, 3> =
RingBufferHeap::new();
assert_eq!(ring_buffer.len(), len(0));
assert_eq!(ring_buffer.head, 0);
assert_eq!(ring_buffer.tail, 0);
assert_eq!(ring_buffer.count, 0);
let mut iter = ring_buffer.iter();
assert_eq!(iter.next(), None);
assert_eq!(ring_buffer.get(0), None);
assert_eq!(ring_buffer.get(1), None);
assert_eq!(ring_buffer.get(2), None);
assert_eq!(ring_buffer.first(), None);
assert_eq!(ring_buffer.last(), None);
}
#[test]
fn test_normal_insert_heap() {
let mut ring_buffer: RingBufferHeap<SmallStringBackingStore, 3> =
RingBufferHeap::new();
ring_buffer.add("Hello".into());
assert_eq!(ring_buffer.len(), len(1));
assert_eq!(ring_buffer.head, 1);
assert_eq!(ring_buffer.tail, 0);
assert_eq!(ring_buffer.count, 1);
let mut iter = ring_buffer.iter();
assert_eq!(iter.next().unwrap(), "Hello");
assert_eq!(iter.next(), None);
assert_eq!(ring_buffer.get(0).unwrap(), "Hello");
assert_eq!(ring_buffer.get(1), None);
assert_eq!(ring_buffer.get(2), None);
assert_eq!(ring_buffer.first().unwrap(), "Hello");
assert_eq!(ring_buffer.last().unwrap(), "Hello");
}
#[test]
fn test_multiple_inserts_heap() {
let mut ring_buffer: RingBufferHeap<SmallStringBackingStore, 3> =
RingBufferHeap::new();
ring_buffer.add("Hello".into());
ring_buffer.add("World".into());
ring_buffer.add("Rust".into());
assert_eq!(ring_buffer.len(), len(3));
assert_eq!(ring_buffer.head, 0);
assert_eq!(ring_buffer.tail, 0);
assert_eq!(ring_buffer.count, 3);
let mut iter = ring_buffer.iter();
assert_eq!(iter.next().unwrap(), "Hello");
assert_eq!(iter.next().unwrap(), "World");
assert_eq!(iter.next().unwrap(), "Rust");
assert_eq!(iter.next(), None);
assert_eq!(ring_buffer.get(0).unwrap(), "Hello");
assert_eq!(ring_buffer.get(1).unwrap(), "World");
assert_eq!(ring_buffer.get(2).unwrap(), "Rust");
assert_eq!(ring_buffer.get(3), None);
assert_eq!(ring_buffer.first().unwrap(), "Hello");
assert_eq!(ring_buffer.last().unwrap(), "Rust");
}
#[test]
fn test_normal_remove_heap() {
let mut ring_buffer: RingBufferHeap<SmallStringBackingStore, 3> =
RingBufferHeap::new();
ring_buffer.add("Hello".into());
ring_buffer.add("World".into());
ring_buffer.add("Rust".into());
ring_buffer.remove();
assert_eq!(ring_buffer.len(), len(2));
assert_eq!(ring_buffer.head, 0);
assert_eq!(ring_buffer.tail, 1);
assert_eq!(ring_buffer.count, 2);
let mut iter = ring_buffer.iter();
assert_eq!(iter.next().unwrap(), "World");
assert_eq!(iter.next().unwrap(), "Rust");
assert_eq!(iter.next(), None);
assert_eq!(ring_buffer.get(0).unwrap(), "World");
assert_eq!(ring_buffer.get(1).unwrap(), "Rust");
assert_eq!(ring_buffer.get(2), None);
assert_eq!(ring_buffer.get(3), None);
assert_eq!(ring_buffer.first().unwrap(), "World");
assert_eq!(ring_buffer.last().unwrap(), "Rust");
}
#[test]
fn test_wrap_around_insert_heap() {
let mut ring_buffer: RingBufferHeap<SmallStringBackingStore, 3> =
RingBufferHeap::new();
ring_buffer.add("Hello".into());
ring_buffer.add("World".into());
ring_buffer.add("Rust".into());
ring_buffer.add("R3BL".into());
assert_eq!(ring_buffer.len(), len(3));
assert_eq!(ring_buffer.head, 1);
assert_eq!(ring_buffer.tail, 1);
assert_eq!(ring_buffer.count, 3);
let mut iter = ring_buffer.iter();
assert_eq!(iter.next().unwrap(), "World");
assert_eq!(iter.next().unwrap(), "Rust");
assert_eq!(iter.next().unwrap(), "R3BL");
assert_eq!(iter.next(), None);
assert_eq!(ring_buffer.get(0).unwrap(), "World");
assert_eq!(ring_buffer.get(1).unwrap(), "Rust");
assert_eq!(ring_buffer.get(2).unwrap(), "R3BL");
assert_eq!(ring_buffer.get(3), None);
assert_eq!(ring_buffer.first().unwrap(), "World");
assert_eq!(ring_buffer.last().unwrap(), "R3BL");
}
#[test]
fn test_wrap_around_remove_heap() {
let mut ring_buffer: RingBufferHeap<SmallStringBackingStore, 3> =
RingBufferHeap::new();
ring_buffer.add("Hello".into());
ring_buffer.add("World".into());
ring_buffer.add("Rust".into());
ring_buffer.add("R3BL".into());
ring_buffer.remove();
assert_eq!(ring_buffer.len(), len(2));
assert_eq!(ring_buffer.head, 1);
assert_eq!(ring_buffer.tail, 2);
assert_eq!(ring_buffer.count, 2);
let mut iter = ring_buffer.iter();
assert_eq!(iter.next().unwrap(), "Rust");
assert_eq!(iter.next().unwrap(), "R3BL");
assert_eq!(iter.next(), None);
assert_eq!(ring_buffer.get(0).unwrap(), "Rust");
assert_eq!(ring_buffer.get(1).unwrap(), "R3BL");
assert_eq!(ring_buffer.get(2), None);
assert_eq!(ring_buffer.get(3), None);
assert_eq!(ring_buffer.first().unwrap(), "Rust");
assert_eq!(ring_buffer.last().unwrap(), "R3BL");
}
#[test]
fn test_clear_heap() {
let mut ring_buffer: RingBufferHeap<SmallStringBackingStore, 3> =
RingBufferHeap::new();
ring_buffer.add("Hello".into());
ring_buffer.add("World".into());
ring_buffer.add("Rust".into());
ring_buffer.clear();
assert_eq!(ring_buffer.len(), len(0));
assert_eq!(ring_buffer.head, 0);
assert_eq!(ring_buffer.tail, 0);
assert_eq!(ring_buffer.count, 0);
let mut iter = ring_buffer.iter();
assert_eq!(iter.next(), None);
assert_eq!(ring_buffer.get(0), None);
assert_eq!(ring_buffer.get(1), None);
assert_eq!(ring_buffer.get(2), None);
assert_eq!(ring_buffer.get(3), None);
assert_eq!(ring_buffer.first(), None);
assert_eq!(ring_buffer.last(), None);
}
#[test]
fn test_normal_truncate() {
let mut vec: Vec<String> = vec![];
vec.push("Hello".into());
vec.push("World".into());
vec.push("Rust".into());
vec.truncate(2);
assert_eq!(vec.len(), 2);
assert_eq!(vec.first().unwrap(), "Hello");
assert_eq!(vec.get(1).unwrap(), "World");
assert_eq!(vec.get(2), None);
let mut ring_buffer: RingBufferHeap<SmallStringBackingStore, 3> =
RingBufferHeap::new();
ring_buffer.add("Hello".into());
ring_buffer.add("World".into());
ring_buffer.add("Rust".into());
ring_buffer.truncate(2);
assert_eq!(ring_buffer.len(), len(2));
assert_eq!(ring_buffer.head, 2);
assert_eq!(ring_buffer.tail, 0);
assert_eq!(ring_buffer.count, 2);
let mut iter = ring_buffer.iter();
assert_eq!(iter.next().unwrap(), "Hello");
assert_eq!(iter.next().unwrap(), "World");
assert_eq!(iter.next(), None);
assert_eq!(ring_buffer.get(0).unwrap(), "Hello");
assert_eq!(ring_buffer.get(1).unwrap(), "World");
assert_eq!(ring_buffer.get(2), None);
assert_eq!(ring_buffer.get(3), None);
assert_eq!(ring_buffer.first().unwrap(), "Hello");
assert_eq!(ring_buffer.last().unwrap(), "World");
}
#[test]
fn test_wrap_around_truncate() {
let mut vec: Vec<String> = vec![];
vec.push("Hello".into());
vec.push("World".into());
vec.push("Rust".into());
vec.truncate(2);
assert_eq!(vec.len(), 2);
assert_eq!(vec.first().unwrap(), "Hello");
assert_eq!(vec.get(1).unwrap(), "World");
assert_eq!(vec.get(2), None);
let mut ring_buffer: RingBufferHeap<SmallStringBackingStore, 3> =
RingBufferHeap::new();
ring_buffer.add("Hello".into());
ring_buffer.add("World".into());
ring_buffer.add("Rust".into());
ring_buffer.add("R3BL".into());
ring_buffer.truncate(2);
assert_eq!(ring_buffer.len(), len(2));
assert_eq!(ring_buffer.head, 0);
assert_eq!(ring_buffer.tail, 1);
assert_eq!(ring_buffer.count, 2);
assert_eq!(ring_buffer.get(0).unwrap(), "World");
assert_eq!(ring_buffer.get(1).unwrap(), "Rust");
assert_eq!(ring_buffer.get(2), None);
assert_eq!(ring_buffer.get(3), None);
let mut iter = ring_buffer.iter();
assert_eq!(iter.next().unwrap(), "World");
assert_eq!(iter.next().unwrap(), "Rust");
assert_eq!(iter.next(), None);
assert_eq!(ring_buffer.first().unwrap(), "World");
assert_eq!(ring_buffer.last().unwrap(), "Rust");
}
}