use crate::header::Counter;
pub trait FrameCounter {
fn next(&mut self) -> Counter;
}
#[derive(Copy, Clone, Debug)]
pub struct MonotonicCounter {
current_counter: u64,
max_counter: u64,
}
impl MonotonicCounter {
pub fn new(max_counter: u64) -> Self {
Self {
current_counter: 0,
max_counter,
}
}
pub fn with_start_value(start_value: u64, max_counter: u64) -> Self {
Self {
current_counter: start_value,
max_counter,
}
}
pub fn current(&self) -> Counter {
self.current_counter
}
}
impl FrameCounter for MonotonicCounter {
fn next(&mut self) -> Counter {
let counter = self.current_counter;
self.current_counter = self.current_counter.wrapping_add(1);
if self.current_counter > self.max_counter {
self.current_counter = 0;
}
counter
}
}
impl Default for MonotonicCounter {
fn default() -> Self {
Self {
current_counter: 0,
max_counter: u64::MAX,
}
}
}
#[cfg(test)]
mod test {
use crate::frame::FrameCounter;
use super::MonotonicCounter;
use pretty_assertions::assert_eq;
#[test]
fn create_increasing_counters() {
let mut counter = MonotonicCounter::default();
for i in 0..10 {
assert_eq!(counter.next(), i);
}
}
#[test]
fn wraps_after_u64_max_was_reached() {
let mut counter = MonotonicCounter::new(u64::MAX);
counter.current_counter = u64::MAX - 1;
assert_eq!(counter.next(), u64::MAX - 1);
assert_eq!(counter.next(), u64::MAX);
assert_eq!(counter.next(), 0);
}
#[test]
fn wraps_after_max_counter_was_reached() {
let max_counter = 1;
let mut counter = MonotonicCounter::new(max_counter);
assert_eq!(counter.next(), 0);
assert_eq!(counter.next(), 1);
assert_eq!(counter.next(), 0);
}
}