use alloc::{
boxed::Box,
string::{String, ToString},
};
use core::{
fmt::Debug,
hash::{BuildHasher, Hash, Hasher},
};
use ahash::RandomState;
use serde::{Deserialize, Serialize};
use super::Observer;
use crate::{
bolts::{ownedref::OwnedRef, tuples::Named},
inputs::UsesInput,
observers::ObserverWithHashField,
Error,
};
#[derive(Serialize, Deserialize, Debug)]
#[serde(bound = "T: serde::de::DeserializeOwned")]
pub struct ValueObserver<'a, T>
where
T: Debug + Serialize,
{
name: String,
pub value: OwnedRef<'a, T>,
}
impl<'a, T> ValueObserver<'a, T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
#[must_use]
pub fn new(name: &'static str, value: &'a T) -> Self {
Self {
name: name.to_string(),
value: OwnedRef::Ref(value),
}
}
#[must_use]
pub fn get_ref(&self) -> &T {
self.value.as_ref()
}
pub fn set(&mut self, new_value: T) {
self.value = OwnedRef::Owned(Box::new(new_value));
}
#[must_use]
pub fn take(self) -> T
where
T: Clone,
{
match self.value {
OwnedRef::Ref(r) => r.clone(),
OwnedRef::Owned(v) => *v,
}
}
}
impl<'a, S, T> Observer<S> for ValueObserver<'a, T>
where
S: UsesInput,
T: Debug + Serialize + serde::de::DeserializeOwned,
{
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
Ok(())
}
}
impl<'a, T> Named for ValueObserver<'a, T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
fn name(&self) -> &str {
&self.name
}
}
impl<'a, T: Hash> ObserverWithHashField for ValueObserver<'a, T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
fn hash(&self) -> Option<u64> {
let mut s = RandomState::with_seeds(1, 2, 3, 4).build_hasher();
Hash::hash(self.value.as_ref(), &mut s);
Some(s.finish())
}
}