#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct WindowBuffer<T> {
buffer: Vec<T>,
cap: usize,
max: usize,
start: usize,
end: usize,
}
impl<T> WindowBuffer<T> {
pub fn with_window(cap: usize) -> Self {
assert!(cap > 0, "WindowBuffer capacity must be > 0");
let max = cap * 2;
Self {
buffer: Vec::with_capacity(max),
cap,
max,
start: 0,
end: 0,
}
}
#[inline]
pub fn push(&mut self, item: T) -> bool {
let mut resized = false;
if self.buffer.len() >= self.cap {
if self.buffer.len() >= self.max {
if self.end >= self.max {
let (front, back) = self.buffer.split_at_mut(self.cap);
front.swap_with_slice(back);
self.start = 0;
self.end = self.cap;
}
self.buffer[self.end] = item;
} else {
self.buffer.push(item);
}
resized = true;
self.start += 1;
self.end += 1;
} else {
self.buffer.push(item);
self.end += 1;
if self.end - self.start > self.cap {
self.start += 1;
}
}
resized
}
#[inline]
pub fn len(&self) -> usize {
self.buffer.len().saturating_sub(self.start)
}
#[inline]
pub fn values(&self) -> &[T] {
&self.buffer[self.start..self.end]
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.values().iter()
}
pub fn as_slice(&self) -> &[T] {
self.values()
}
}
impl<T: Clone> Clone for WindowBuffer<T> {
fn clone(&self) -> Self {
Self {
buffer: self.buffer.clone(),
cap: self.cap,
max: self.max,
start: self.start,
end: self.end,
}
}
}
impl<T: PartialEq> PartialEq for WindowBuffer<T> {
fn eq(&self, other: &Self) -> bool {
self.values() == other.values()
}
}
impl<T: Debug> Debug for WindowBuffer<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("WindowBuffer")
.field("capacity", &self.cap)
.field("values", &self.values())
.finish()
}
}
#[cfg(test)]
mod tests {
use super::WindowBuffer;
#[test]
fn ring_buffer_works() {
let mut buffer = WindowBuffer::with_window(5);
for i in 0..20 {
buffer.push(i);
}
}
}