use alloc::collections::VecDeque;
use core::time::Duration;
use libafl_bolts::current_time;
#[derive(Debug, Copy, Clone)]
pub struct TimedStat {
pub time: Duration,
pub item: f64,
}
#[derive(Debug, Clone)]
pub struct TimedStats {
pub series: VecDeque<TimedStat>,
pub window: Duration,
pub retention: Duration,
}
impl TimedStats {
#[must_use]
pub fn new(window: Duration) -> Self {
Self {
series: VecDeque::new(),
window,
retention: window,
}
}
pub fn add(&mut self, time: Duration, item: f64) {
if self.series.is_empty() || (self.series.back().unwrap().item - item).abs() > f64::EPSILON
{
while self.series.front().is_some()
&& time
.checked_sub(self.series.front().unwrap().time)
.unwrap_or(self.retention)
>= self.retention
{
self.series.pop_front();
}
self.series.push_back(TimedStat { time, item });
}
}
pub fn add_now(&mut self, item: f64) {
let time = current_time();
self.add(time, item);
}
pub fn update_window(&mut self, window: Duration) {
let default_stat = TimedStat {
time: Duration::from_secs(0),
item: 0.0,
};
self.window = window;
if window > self.retention {
self.retention = window;
}
while !self.series.is_empty()
&& self
.series
.back()
.unwrap_or(&default_stat)
.time
.checked_sub(self.series.front().unwrap_or(&default_stat).time)
.unwrap_or(self.retention)
>= self.retention
{
self.series.pop_front();
}
}
}