pub mod map;
pub use map::*;
pub mod cmp;
pub use cmp::*;
pub mod concolic;
use alloc::string::{String, ToString};
use core::time::Duration;
use serde::{Deserialize, Serialize};
use crate::{
bolts::{
current_time,
tuples::{MatchName, Named},
},
Error,
};
pub trait Observer<I, S>: Named {
#[inline]
fn flush(&mut self) -> Result<(), Error> {
Ok(())
}
#[inline]
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
Ok(())
}
#[inline]
fn post_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
Ok(())
}
}
pub trait ObserversTuple<I, S>: MatchName {
fn pre_exec_all(&mut self, state: &mut S, input: &I) -> Result<(), Error>;
fn post_exec_all(&mut self, state: &mut S, input: &I) -> Result<(), Error>;
}
impl<I, S> ObserversTuple<I, S> for () {
fn pre_exec_all(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
Ok(())
}
fn post_exec_all(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
Ok(())
}
}
impl<Head, Tail, I, S> ObserversTuple<I, S> for (Head, Tail)
where
Head: Observer<I, S>,
Tail: ObserversTuple<I, S>,
{
fn pre_exec_all(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
self.0.pre_exec(state, input)?;
self.1.pre_exec_all(state, input)
}
fn post_exec_all(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
self.0.post_exec(state, input)?;
self.1.post_exec_all(state, input)
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct TimeObserver {
name: String,
start_time: Duration,
last_runtime: Option<Duration>,
}
impl TimeObserver {
#[must_use]
pub fn new(name: &'static str) -> Self {
Self {
name: name.to_string(),
start_time: Duration::from_secs(0),
last_runtime: None,
}
}
#[must_use]
pub fn last_runtime(&self) -> &Option<Duration> {
&self.last_runtime
}
}
impl<I, S> Observer<I, S> for TimeObserver {
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
self.last_runtime = None;
self.start_time = current_time();
Ok(())
}
fn post_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
self.last_runtime = current_time().checked_sub(self.start_time);
Ok(())
}
}
impl Named for TimeObserver {
fn name(&self) -> &str {
&self.name
}
}
#[cfg(feature = "std")]
#[cfg(test)]
mod tests {
use crate::{
bolts::tuples::{tuple_list, tuple_list_type, Named},
observers::{StdMapObserver, TimeObserver},
};
static mut MAP: [u32; 4] = [0; 4];
#[test]
fn test_observer_serde() {
let obv = tuple_list!(
TimeObserver::new("time"),
StdMapObserver::new("map", unsafe { &mut MAP })
);
let vec = postcard::to_allocvec(&obv).unwrap();
println!("{:?}", vec);
let obv2: tuple_list_type!(TimeObserver, StdMapObserver<u32>) =
postcard::from_bytes(&vec).unwrap();
assert_eq!(obv.0.name(), obv2.0.name());
}
}