62 lines
1.7 KiB
Rust
62 lines
1.7 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
use std::{collections::HashMap, ops::Deref};
|
|
|
|
/// A struct to keep track of historical changes to a value.
|
|
/// This struct represents a value that has a current state and a history of previous states.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
pub struct Historic<T> {
|
|
/// The current value
|
|
pub current: T,
|
|
/// A map of timestamps (RFC 3339) to historical values.
|
|
pub changes: HashMap<String, T>,
|
|
}
|
|
|
|
impl<T: Clone> Historic<T> {
|
|
/// Create a new value with tracked history
|
|
pub fn new(value: T) -> Historic<T> {
|
|
let mut changes = HashMap::new();
|
|
changes.insert(chrono::Utc::now().to_rfc3339(), value.clone());
|
|
|
|
Self {
|
|
current: value,
|
|
changes,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T: Default + Clone> Historic<T> {
|
|
/// Create a new tracked value initialized with Default
|
|
pub fn new_default() -> Historic<T> {
|
|
Self::new(T::default())
|
|
}
|
|
}
|
|
|
|
impl<T: Clone> Historic<T> {
|
|
/// Update the value. The change will be recorded.
|
|
/// Will record a change even if the value is the same as the current one.
|
|
pub fn update(&mut self, value: T) {
|
|
self.changes
|
|
.insert(chrono::Utc::now().to_rfc3339(), value.clone());
|
|
self.current = value;
|
|
}
|
|
}
|
|
|
|
impl<T: Clone + std::cmp::PartialEq> Historic<T> {
|
|
/// Update the value. The change will be recorded.
|
|
/// If the value is equal to the current one, no update will take place.
|
|
pub fn update_unique(&mut self, value: T) {
|
|
if self.current == value {
|
|
return;
|
|
}
|
|
|
|
self.update(value);
|
|
}
|
|
}
|
|
|
|
impl<T> Deref for Historic<T> {
|
|
type Target = T;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.current
|
|
}
|
|
}
|