use std::ops::Deref;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Stamped<T> {
pub value: T,
pub heard: u64,
pub changed: u64,
}
impl<T> Stamped<T> {
#[must_use]
pub const fn new(now: u64, value: T) -> Stamped<T> {
Stamped { value, heard: now, changed: now }
}
#[must_use]
pub const fn age(&self, now: u64) -> u64 {
now.saturating_sub(self.heard)
}
pub fn touch(&mut self, now: u64, changed: bool) {
self.heard = self.heard.max(now);
if changed {
self.changed = self.changed.max(now);
}
}
}
impl<T: PartialEq> Stamped<T> {
pub fn set(&mut self, now: u64, value: T) -> bool {
let changed = self.value != value;
if changed {
self.value = value;
}
self.touch(now, changed);
changed
}
}
impl<T> Deref for Stamped<T> {
type Target = T;
fn deref(&self) -> &T {
&self.value
}
}
pub(crate) fn put<T: PartialEq>(slot: &mut Option<Stamped<T>>, now: u64, value: T) -> bool {
match slot {
Some(held) => held.set(now, value),
None => {
*slot = Some(Stamped::new(now, value));
true
}
}
}