use alloc::{
boxed::Box,
string::{String, ToString},
};
use core::{
cell::{Ref, RefCell},
fmt::Debug,
hash::Hash,
ops::Deref,
};
use ahash::RandomState;
use libafl_bolts::{ownedref::OwnedRef, Named};
use serde::{Deserialize, Serialize};
use super::Observer;
use crate::{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> {
Some(RandomState::with_seeds(1, 2, 3, 4).hash_one(self.value.as_ref()))
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(bound = "T: serde::de::DeserializeOwned")]
pub struct RefCellValueObserver<'a, T>
where
T: Debug + Serialize,
{
name: String,
pub value: OwnedRef<'a, RefCell<T>>,
}
impl<'a, T> RefCellValueObserver<'a, T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
#[must_use]
pub fn new(name: &'static str, value: &'a RefCell<T>) -> Self {
Self {
name: name.to_string(),
value: OwnedRef::Ref(value),
}
}
#[must_use]
pub fn get_ref<'b>(&'b self) -> Ref<'a, T>
where
'b: 'a,
{
self.value.as_ref().borrow()
}
pub fn set(&mut self, new_value: T) {
self.value.as_ref().replace(new_value);
}
#[must_use]
pub fn take(self) -> T
where
T: Clone,
{
match self.value {
OwnedRef::Ref(r) => r.borrow().deref().clone(),
OwnedRef::Owned(v) => v.borrow().clone(),
}
}
}
impl<'a, S, T> Observer<S> for RefCellValueObserver<'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 RefCellValueObserver<'a, T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
fn name(&self) -> &str {
&self.name
}
}
impl<'a, T: Hash> ObserverWithHashField for RefCellValueObserver<'a, T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
fn hash(&self) -> Option<u64> {
Some(RandomState::with_seeds(1, 2, 3, 4).hash_one(&*self.value.as_ref().borrow()))
}
}