use generic_array::{ArrayLength, GenericArray, sequence::GenericSequence};
#[derive(Clone)]
pub struct HistoryBuffer<T, N>
where
N: ArrayLength<T>,
{
data: GenericArray<T, N>,
write_at: usize,
}
impl<T, N> HistoryBuffer<T, N>
where
N: ArrayLength<T>,
T: Default,
{
pub fn new() -> Self {
Self {
data: Default::default(),
write_at: 0,
}
}
pub fn clear(&mut self) {
*self = Self::new();
}
}
impl<T, N> HistoryBuffer<T, N>
where
N: ArrayLength<T>,
T: Clone,
{
pub fn new_with(t: T) -> Self {
Self {
data: GenericArray::generate(|_| t.clone()),
write_at: 0,
}
}
pub fn clear_with(&mut self, t: T) {
*self = Self::new_with(t);
}
}
impl<T, N> HistoryBuffer<T, N>
where
N: ArrayLength<T>,
{
pub fn len(&self) -> usize {
self.data.len()
}
pub fn write(&mut self, t: T) {
self.data[self.write_at] = t;
self.write_at = (self.write_at + 1) % self.len();
}
pub fn extend_from_slice(&mut self, other: &[T])
where
T: Clone,
{
for item in other {
self.write(item.clone());
}
}
pub fn recent(&self) -> &T {
&self.data[(self.write_at + self.len() - 1) % self.len()]
}
pub fn as_slice(&self) -> &[T] {
&self.data
}
}
impl<T, N> Extend<T> for HistoryBuffer<T, N>
where
N: ArrayLength<T>,
{
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = T>,
{
for item in iter.into_iter() {
self.write(item);
}
}
}
impl<'a, T, N> Extend<&'a T> for HistoryBuffer<T, N>
where
T: 'a + Clone,
N: ArrayLength<T>,
{
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = &'a T>,
{
self.extend(iter.into_iter().cloned())
}
}
#[cfg(test)]
mod tests {
use crate::{consts::*, HistoryBuffer};
#[test]
fn new() {
let x: HistoryBuffer<u8, U4> = HistoryBuffer::new_with(1);
assert_eq!(x.len(), 4);
assert_eq!(x.as_slice(), [1; 4]);
let x: HistoryBuffer<u8, U4> = HistoryBuffer::new();
assert_eq!(x.as_slice(), [0; 4]);
}
#[test]
fn write() {
let mut x: HistoryBuffer<u8, U4> = HistoryBuffer::new();
x.write(1);
x.write(4);
assert_eq!(x.as_slice(), [1, 4, 0, 0]);
x.write(5);
x.write(6);
x.write(10);
assert_eq!(x.as_slice(), [10, 4, 5, 6]);
x.extend([11, 12].iter());
assert_eq!(x.as_slice(), [10, 11, 12, 6]);
}
#[test]
fn clear() {
let mut x: HistoryBuffer<u8, U4> = HistoryBuffer::new_with(1);
x.clear();
assert_eq!(x.as_slice(), [0; 4]);
let mut x: HistoryBuffer<u8, U4> = HistoryBuffer::new();
x.clear_with(1);
assert_eq!(x.as_slice(), [1; 4]);
}
#[test]
fn recent() {
let mut x: HistoryBuffer<u8, U4> = HistoryBuffer::new();
assert_eq!(x.recent(), &0);
x.write(1);
x.write(4);
assert_eq!(x.recent(), &4);
x.write(5);
x.write(6);
x.write(10);
assert_eq!(x.recent(), &10);
}
#[test]
fn as_slice() {
let mut x: HistoryBuffer<u8, U4> = HistoryBuffer::new();
x.extend([1, 2, 3, 4, 5].iter());
assert_eq!(x.as_slice(), [5, 2, 3, 4]);
}
}