use std::collections::VecDeque;
#[derive(Debug, Clone)]
pub struct RingBuffer<T> {
buffer: VecDeque<T>,
capacity: usize,
}
impl<T> RingBuffer<T> {
pub fn new(capacity: usize) -> Self {
Self {
buffer: VecDeque::with_capacity(capacity),
capacity: capacity.max(1),
}
}
pub fn push(&mut self, item: T) {
if self.buffer.len() == self.capacity {
self.buffer.pop_front();
}
self.buffer.push_back(item);
}
pub fn pop(&mut self) -> Option<T> {
self.buffer.pop_back()
}
pub fn len(&self) -> usize {
self.buffer.len()
}
pub fn is_empty(&self) -> bool {
self.buffer.is_empty()
}
pub fn is_full(&self) -> bool {
self.buffer.len() == self.capacity
}
pub fn capacity(&self) -> usize {
self.capacity
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.buffer.iter()
}
pub fn iter_recent(&self) -> impl Iterator<Item = &T> {
self.buffer.iter().rev()
}
pub fn last(&self) -> Option<&T> {
self.buffer.back()
}
pub fn first(&self) -> Option<&T> {
self.buffer.front()
}
pub fn clear(&mut self) {
self.buffer.clear();
}
pub fn to_vec(&self) -> Vec<T>
where
T: Clone,
{
self.buffer.iter().cloned().collect()
}
pub fn to_vec_recent(&self) -> Vec<T>
where
T: Clone,
{
self.buffer.iter().rev().cloned().collect()
}
}
impl<T: Clone> RingBuffer<T> {
pub fn from_vec(items: Vec<T>, capacity: usize) -> Self {
let capacity = capacity.max(1);
let mut buffer = VecDeque::with_capacity(capacity);
let start = items.len().saturating_sub(capacity);
for item in items.into_iter().skip(start) {
if buffer.len() < capacity {
buffer.push_back(item);
}
}
Self { buffer, capacity }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ring_buffer_basic() {
let mut buf: RingBuffer<i32> = RingBuffer::new(3);
buf.push(1);
buf.push(2);
buf.push(3);
assert_eq!(buf.len(), 3);
assert_eq!(buf.to_vec(), vec![1, 2, 3]);
}
#[test]
fn test_ring_buffer_overflow() {
let mut buf: RingBuffer<i32> = RingBuffer::new(3);
buf.push(1);
buf.push(2);
buf.push(3);
buf.push(4);
assert_eq!(buf.len(), 3);
assert_eq!(buf.to_vec(), vec![2, 3, 4]);
}
#[test]
fn test_ring_buffer_iter_recent() {
let mut buf: RingBuffer<i32> = RingBuffer::new(3);
buf.push(1);
buf.push(2);
buf.push(3);
let recent: Vec<_> = buf.iter_recent().copied().collect();
assert_eq!(recent, vec![3, 2, 1]);
}
#[test]
fn test_ring_buffer_pop() {
let mut buf: RingBuffer<i32> = RingBuffer::new(3);
buf.push(1);
buf.push(2);
assert_eq!(buf.pop(), Some(2));
assert_eq!(buf.len(), 1);
}
}