use super::chunk::{ChunkSummary, Chunker};
use super::{Id, LogValue};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ByCounter {
pub counter: Id,
pub interval: u64,
state: State,
}
impl ByCounter {
#[must_use]
#[inline]
pub const fn new(counter: Id, interval: u64) -> Self {
Self {
counter,
interval,
state: State::NoFlush,
}
}
pub fn of_path<T: IntoIterator<Item = &'static str>>(path: T, interval: u64) -> Self {
Self::new(Id::from_iter(path), interval)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
enum State {
NoFlush,
IdMatch,
Flush,
}
impl Chunker for ByCounter {
#[inline]
fn note_log(&mut self, id: &Id, _: &LogValue) {
debug_assert!(
matches!(self.state, State::NoFlush | State::Flush),
"note_log following note_log without note_log_summary in between"
);
if matches!(self.state, State::NoFlush) && &self.counter == id {
self.state = State::IdMatch;
}
}
#[inline]
fn note_log_summary(&mut self, summary: &ChunkSummary) {
if matches!(self.state, State::IdMatch) {
if let ChunkSummary::Counter {
increment,
initial_value,
} = summary
{
if (increment + initial_value) % self.interval == 0 {
self.state = State::Flush;
} else {
self.state = State::NoFlush;
}
} else {
panic!("Target ID {} is not a counter", self.counter);
}
}
}
#[inline]
fn flush_group_end(&mut self) -> bool {
matches!(self.state, State::Flush)
}
#[inline]
fn note_flush(&mut self) {
self.state = State::NoFlush;
}
}