use crate::{Error, Reset};
pub mod buckets;
pub mod vector;
pub use buckets::Buckets;
pub use vector::Vector;
#[derive(Default)]
pub struct Value<T> {
value: Option<T>,
dirty: bool,
}
impl<T> Value<T> {
pub fn new() -> Self {
Value {
value: None,
dirty: false,
}
}
pub fn set(&mut self, value: T) {
self.value = Some(value);
self.dirty = true;
}
pub fn get(&self) -> Result<&T, Error> {
self.value.as_ref().ok_or(Error::UninitialisedValue)
}
pub fn get_mut(&mut self) -> Result<&mut T, Error> {
self.value.as_mut().ok_or(Error::UninitialisedValue)
}
pub fn touch(&mut self) {
if self.value.is_some() {
self.dirty = true;
}
}
pub fn is_updated(&self) -> bool {
self.dirty
}
pub fn has_value(&self) -> bool {
self.value.is_some()
}
pub fn get_valid(&self) -> Option<&T> {
self.value.as_ref()
}
pub fn is_valid(&self) -> bool {
self.value.is_some()
}
pub fn invalidate(&mut self) {
if self.value.take().is_some() {
self.dirty = true;
}
}
}
impl<T> Reset for Value<T> {
type Error = Error;
fn reset(&mut self) -> Result<(), Error> {
self.dirty = false;
Ok(())
}
}
impl<T> crate::Updated for Value<T> {
fn is_updated(&self) -> bool {
self.is_updated() }
}
impl<T: PartialEq> PartialEq<T> for Value<T> {
fn eq(&self, other: &T) -> bool {
self.value.as_ref().is_some_and(|v| v == other)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_initial_state() {
let value: Value<i32> = Value::new();
assert!(!value.has_value());
}
#[test]
fn test_set_and_get() {
let mut value = Value::new();
value.set(42);
assert_eq!(value.get(), Ok(&42));
}
#[test]
fn test_touch() {
let mut value = Value::new();
value.set(42);
value.touch();
assert!(value.is_updated());
}
#[test]
fn test_reset() {
let mut value = Value::new();
assert!(!value.has_value());
value.set(42);
assert!(value.has_value());
assert!(value.is_updated());
assert_eq!(*value.get().unwrap(), 42);
assert!(value.reset().is_ok());
assert!(!value.is_updated());
assert_eq!(*value.get().unwrap(), 42);
value.touch();
assert!(value.is_updated());
assert_eq!(*value.get().unwrap(), 42);
}
#[test]
fn test_uninitialised_get() {
let value: Value<i32> = Value::new();
assert_eq!(value.get(), Err(Error::UninitialisedValue));
}
#[test]
fn test_reset_uninitialised() {
let mut value: Value<i32> = Value::new();
assert_eq!(value.reset(), Ok(()));
assert!(!value.has_value());
}
#[test]
fn get_valid_returns_some_when_set_or_updated() {
let mut value: Value<i32> = Value::new();
assert_eq!(value.get_valid(), None);
assert!(!value.is_valid());
value.set(7);
assert_eq!(value.get_valid(), Some(&7));
assert!(value.is_valid());
assert!(value.is_updated());
value.reset().unwrap();
assert_eq!(value.get_valid(), Some(&7));
assert!(value.is_valid());
assert!(!value.is_updated());
}
#[test]
fn invalidate_drops_value_to_uninitialised() {
let mut value: Value<i32> = Value::new();
value.set(42);
assert!(value.is_valid());
value.invalidate();
assert!(!value.is_valid());
assert_eq!(value.get_valid(), None);
assert_eq!(value.get(), Err(Error::UninitialisedValue));
value.set(99);
assert_eq!(value.get_valid(), Some(&99));
assert!(value.is_updated());
}
#[test]
fn invalidate_marks_dirty_and_clears_valid() {
let mut value: Value<i32> = Value::new();
value.set(42);
value.reset().unwrap(); assert!(value.is_valid());
assert!(!value.is_updated());
value.invalidate();
assert!(!value.is_valid()); assert!(value.is_updated()); assert_eq!(value.get_valid(), None);
value.reset().unwrap();
assert!(!value.is_valid());
assert!(!value.is_updated());
}
#[test]
fn invalidate_on_uninitialised_is_idempotent_and_clean() {
let mut value: Value<i32> = Value::new();
value.invalidate();
value.invalidate();
assert!(!value.is_valid());
assert!(!value.is_updated());
}
}