use alloc::{
boxed::Box,
collections::{BTreeMap, btree_map::Entry},
sync::Arc,
vec::Vec,
};
use core::{error::Error, fmt, fmt::Debug};
use miden_core::{DebugOptions, EventId, EventName, sys_events::SystemEvent};
use crate::{AdviceMutation, ExecutionError, ProcessState};
pub trait EventHandler: Send + Sync + 'static {
fn on_event(&self, process: &ProcessState) -> Result<Vec<AdviceMutation>, EventError>;
}
impl<F> EventHandler for F
where
F: for<'a> Fn(&'a ProcessState) -> Result<Vec<AdviceMutation>, EventError>
+ Send
+ Sync
+ 'static,
{
fn on_event(&self, process: &ProcessState) -> Result<Vec<AdviceMutation>, EventError> {
self(process)
}
}
pub struct NoopEventHandler;
impl EventHandler for NoopEventHandler {
fn on_event(&self, _process: &ProcessState) -> Result<Vec<AdviceMutation>, EventError> {
Ok(Vec::new())
}
}
pub type EventError = Box<dyn Error + Send + Sync + 'static>;
#[derive(Default)]
pub struct EventHandlerRegistry {
handlers: BTreeMap<EventId, (EventName, Arc<dyn EventHandler>)>,
}
impl EventHandlerRegistry {
pub fn new() -> Self {
Self { handlers: BTreeMap::new() }
}
pub fn register(
&mut self,
event: EventName,
handler: Arc<dyn EventHandler>,
) -> Result<(), ExecutionError> {
if SystemEvent::from_name(event.as_str()).is_some() {
return Err(ExecutionError::ReservedEventNamespace { event });
}
let id = event.to_event_id();
match self.handlers.entry(id) {
Entry::Vacant(e) => e.insert((event, handler)),
Entry::Occupied(_) => return Err(ExecutionError::DuplicateEventHandler { event }),
};
Ok(())
}
pub fn unregister(&mut self, id: EventId) -> bool {
self.handlers.remove(&id).is_some()
}
pub fn resolve_event(&self, id: EventId) -> Option<&EventName> {
self.handlers.get(&id).map(|(event, _)| event)
}
pub fn handle_event(
&self,
id: EventId,
process: &ProcessState,
) -> Result<Option<Vec<AdviceMutation>>, EventError> {
if let Some((_event_name, handler)) = self.handlers.get(&id) {
let mutations = handler.on_event(process)?;
return Ok(Some(mutations));
}
Ok(None)
}
}
impl Debug for EventHandlerRegistry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let events: Vec<_> = self.handlers.values().map(|(event, _)| event).collect();
f.debug_struct("EventHandlerRegistry").field("handlers", &events).finish()
}
}
pub trait DebugHandler: Sync {
fn on_debug(
&mut self,
process: &ProcessState,
options: &DebugOptions,
) -> Result<(), ExecutionError> {
let mut handler = crate::host::debug::DefaultDebugHandler::default();
handler.on_debug(process, options)
}
fn on_trace(&mut self, process: &ProcessState, trace_id: u32) -> Result<(), ExecutionError> {
let _ = (&process, trace_id);
#[cfg(feature = "std")]
std::println!(
"Trace with id {} emitted at step {} in context {}",
trace_id,
process.clk(),
process.ctx()
);
Ok(())
}
}