use std::cmp::min;
use super::traits::Rolling;
#[derive(Debug, Clone, Default)]
pub struct RollingBuffer<T>
where
T: Clone
{
size: usize,
vec: Vec<T>,
last_removed: Option<T>,
count: usize,
}
impl<T> Rolling<T> for RollingBuffer<T>
where
T: Clone + Default
{
fn new(size: usize) -> Self {
Self {
size,
vec: if size > 0 {
vec![T::default(); size]
} else {
Vec::new()
},
last_removed: None,
count: 0,
}
}
fn push(&mut self, value: T) {
if self.size > 0 {
let index = self.count as usize % self.size;
self.last_removed = Some(std::mem::replace(&mut self.vec[index], value));
} else {
self.vec.push(value);
}
self.count += 1;
}
fn get(&self, i: usize) -> Option<&T> {
if self.size > 0 {
Some(&self.vec[i % self.size])
} else if i < self.vec.len() {
Some(&self.vec[i])
} else {
None
}
}
fn last(&self) -> Option<&T> {
if self.count == 0 {
None
} else if self.size > 0 {
let index = (self.count as usize - 1) % self.size;
Some(&self.vec[index])
} else {
Some(&self.vec[self.vec.len() - 1])
}
}
fn last_mut(&mut self) -> Option<&mut T> {
if self.count == 0 {
None
} else if self.size > 0 {
let index = (self.count as usize - 1) % self.size;
Some(&mut self.vec[index])
} else {
let index = self.vec.len() - 1;
Some(&mut self.vec[index])
}
}
fn first(&self) -> Option<&T> {
if self.count == 0 {
None
} else if self.size > 0 {
if self.count <= self.size {
Some(&self.vec[0])
} else {
let index = (self.count as usize) % self.size;
Some(&self.vec[index])
}
} else {
Some(&self.vec[0])
}
}
fn len(&self) -> usize {
if self.count < self.size {
self.count as usize
} else {
self.vec.len()
}
}
fn size(&self) -> usize {
self.size
}
fn raw(&self) -> &Vec<T> {
&self.vec
}
fn last_removed(&self) -> &Option<T> {
&self.last_removed
}
fn count(&self) -> usize {
self.count as usize
}
fn is_empty(&self) -> bool {
self.count == 0
}
fn to_vec(&self) -> Vec<T> {
if self.size > 0 {
let start = if self.count <= self.size {
0 as usize
} else {
self.count % self.size
};
let mut vec = Vec::<T>::new();
for i in start..start + min(self.size, self.count) {
vec.push(self.vec[i % self.size].clone());
}
vec
} else {
self.vec.clone()
}
}
}