use std::time;
use std::{fmt, iter::DoubleEndedIterator, mem, vec::Vec};
pub struct HistoryBuffer<T> {
max_size: usize,
write_index: usize,
buffer: Vec<T>,
last_data_at: time::Instant,
}
impl<T> HistoryBuffer<T> {
pub fn new(max_size: usize) -> Self {
HistoryBuffer {
max_size,
write_index: 0,
buffer: Vec::with_capacity(max_size),
last_data_at: time::Instant::now(),
}
}
pub fn is_empty(&self) -> bool {
self.buffer.len() == 0
}
pub fn is_full(&self) -> bool {
self.buffer.len() == self.max_size
}
pub fn max_len(&self) -> usize {
self.max_size
}
pub fn len(&self) -> usize {
self.buffer.len()
}
pub fn clear(&mut self) {
self.write_index = 0;
self.buffer.clear();
}
pub fn most_recent(&self) -> Option<&T> {
if self.is_empty() {
None
} else {
if self.write_index == 0 {
self.buffer.last()
} else {
Some(&self.buffer[self.write_index - 1])
}
}
}
pub fn write(&mut self, val: T) -> Option<T> {
let r = if self.is_full() {
Some(mem::replace(&mut self.buffer[self.write_index], val))
} else {
self.buffer.push(val);
None
};
self.write_index = (self.write_index.wrapping_add(1)) % self.max_size;
self.last_data_at = time::Instant::now();
r
}
pub fn duration_since_last_measurement(&self) -> Option<time::Duration> {
if !self.is_empty() {
let now = time::Instant::now();
Some(now.duration_since(self.last_data_at))
} else {
None
}
}
pub fn all_unsorted(&self) -> &[T] {
&self.buffer
}
pub fn all(&self) -> impl DoubleEndedIterator<Item = &T> {
let write_index = self.write_index;
self.buffer[write_index..]
.iter()
.chain(self.buffer[..write_index].iter())
}
}
impl<T> fmt::Debug for HistoryBuffer<T>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_list().entries(self.all()).finish()
}
}