pub mod simple;
pub use simple::*;
pub mod llmp;
pub use llmp::*;
use alloc::{string::String, vec::Vec};
use core::{fmt, marker::PhantomData, time::Duration};
use serde::{Deserialize, Serialize};
use crate::{
corpus::CorpusScheduler,
executors::{Executor, HasObservers},
inputs::Input,
observers::ObserversTuple,
Error,
};
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
pub enum LogSeverity {
Debug,
Info,
Warn,
Error,
}
impl fmt::Display for LogSeverity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
LogSeverity::Debug => write!(f, "Debug"),
LogSeverity::Info => write!(f, "Info"),
LogSeverity::Warn => write!(f, "Warn"),
LogSeverity::Error => write!(f, "Error"),
}
}
}
#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
pub enum BrokerEventResult {
Handled,
Forward,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")]
pub enum Event<I>
where
I: Input,
{
NewTestcase {
input: I,
observers_buf: Vec<u8>,
corpus_size: usize,
client_config: String,
time: Duration,
executions: usize,
},
UpdateStats {
time: Duration,
executions: usize,
phantom: PhantomData<I>,
},
Objective {
objective_size: usize,
},
Log {
severity_level: LogSeverity,
message: String,
phantom: PhantomData<I>,
},
}
impl<I> Event<I>
where
I: Input,
{
fn name(&self) -> &str {
match self {
Event::NewTestcase {
input: _,
client_config: _,
corpus_size: _,
observers_buf: _,
time: _,
executions: _,
} => "New Testcase",
Event::UpdateStats {
time: _,
executions: _,
phantom: _,
} => "Stats",
Event::Objective { objective_size: _ } => "Objective",
Event::Log {
severity_level: _,
message: _,
phantom: _,
} => "Log",
}
}
}
pub trait EventManager<I, S>
where
I: Input,
{
fn process<CS, E, OT>(
&mut self,
state: &mut S,
executor: &mut E,
scheduler: &CS,
) -> Result<usize, Error>
where
CS: CorpusScheduler<I, S>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple;
fn serialize_observers<OT>(&mut self, observers: &OT) -> Result<Vec<u8>, Error>
where
OT: ObserversTuple,
{
Ok(postcard::to_allocvec(observers)?)
}
fn deserialize_observers<OT>(&mut self, observers_buf: &[u8]) -> Result<OT, Error>
where
OT: ObserversTuple,
{
Ok(postcard::from_bytes(observers_buf)?)
}
#[inline]
fn on_restart(&mut self, _state: &mut S) -> Result<(), Error> {
Ok(())
}
#[inline]
fn await_restart_safe(&mut self) {}
fn fire(&mut self, state: &mut S, event: Event<I>) -> Result<(), Error>;
}
#[derive(Copy, Clone, Debug)]
pub struct NopEventManager<I, S> {
phantom: PhantomData<(I, S)>,
}
impl<I, S> EventManager<I, S> for NopEventManager<I, S>
where
I: Input,
{
fn process<CS, E, OT>(
&mut self,
_state: &mut S,
_executor: &mut E,
_scheduler: &CS,
) -> Result<usize, Error>
where
CS: CorpusScheduler<I, S>,
E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple,
{
Ok(0)
}
fn fire(&mut self, _state: &mut S, _event: Event<I>) -> Result<(), Error> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use tuple_list::tuple_list_type;
use crate::{
bolts::tuples::{tuple_list, Named},
events::Event,
inputs::bytes::BytesInput,
observers::StdMapObserver,
utils::current_time,
};
static mut MAP: [u32; 4] = [0; 4];
#[test]
fn test_event_serde() {
let obv = StdMapObserver::new("test", unsafe { &mut MAP });
let map = tuple_list!(obv);
let observers_buf = postcard::to_allocvec(&map).unwrap();
let i = BytesInput::new(vec![0]);
let e = Event::NewTestcase {
input: i,
observers_buf,
corpus_size: 123,
client_config: "conf".into(),
time: current_time(),
executions: 0,
};
let serialized = postcard::to_allocvec(&e).unwrap();
let d = postcard::from_bytes::<Event<BytesInput>>(&serialized).unwrap();
match d {
Event::NewTestcase {
input: _,
observers_buf,
corpus_size: _,
client_config: _,
time: _,
executions: _,
} => {
let o: tuple_list_type!(StdMapObserver::<u32>) =
postcard::from_bytes(&observers_buf).unwrap();
assert_eq!("test", o.0.name());
}
_ => panic!("mistmatch"),
};
}
}