Skip to main content

miden_processor/host/
handlers.rs

1use alloc::{
2    boxed::Box,
3    collections::{BTreeMap, btree_map::Entry},
4    sync::Arc,
5    vec::Vec,
6};
7use core::{error::Error, fmt, fmt::Debug};
8
9use miden_core::{
10    events::{EventId, EventName, SystemEvent},
11    operations::DebugOptions,
12};
13
14use crate::{ExecutionError, ProcessorState, advice::AdviceMutation};
15
16// EVENT HANDLER TRAIT
17// ================================================================================================
18
19/// An [`EventHandler`] defines a function that that can be called from the processor which can
20/// read the VM state and modify the state of the advice provider.
21///
22/// A struct implementing this trait can access its own state, but any output it produces must
23/// be stored in the process's advice provider.
24pub trait EventHandler: Send + Sync + 'static {
25    /// Handles the event when triggered.
26    fn on_event(&self, process: &ProcessorState) -> Result<Vec<AdviceMutation>, EventError>;
27}
28
29/// Default implementation for both free functions and closures with signature
30/// `fn(&ProcessorState) -> Result<(), HandlerError>`
31impl<F> EventHandler for F
32where
33    F: for<'a> Fn(&'a ProcessorState) -> Result<Vec<AdviceMutation>, EventError>
34        + Send
35        + Sync
36        + 'static,
37{
38    fn on_event(&self, process: &ProcessorState) -> Result<Vec<AdviceMutation>, EventError> {
39        self(process)
40    }
41}
42
43/// A handler which ignores the process state and leaves the `AdviceProvider` unchanged.
44pub struct NoopEventHandler;
45
46impl EventHandler for NoopEventHandler {
47    fn on_event(&self, _process: &ProcessorState) -> Result<Vec<AdviceMutation>, EventError> {
48        Ok(Vec::new())
49    }
50}
51
52// EVENT ERROR
53// ================================================================================================
54
55/// A generic [`Error`] wrapper allowing handlers to return errors to the Host caller.
56///
57/// Error handlers can define their own [`Error`] type which can be seamlessly converted
58/// into this type since it is a [`Box`].
59///
60/// # Example
61///
62/// ```rust, ignore
63/// pub struct MyError{ /* ... */ };
64///
65/// fn try_something() -> Result<(), MyError> { /* ... */ }
66///
67/// fn my_handler(process: &mut ProcessorState) -> Result<(), HandlerError> {
68///     // ...
69///     try_something()?;
70///     // ...
71///     Ok(())
72/// }
73/// ```
74pub type EventError = Box<dyn Error + Send + Sync + 'static>;
75
76// DEBUG AND TRACE ERRORS
77// ================================================================================================
78
79/// A generic [`Error`] wrapper for debug handler errors.
80///
81/// Debug handlers can define their own [`Error`] type which can be seamlessly converted
82/// into this type since it is a [`Box`].
83pub type DebugError = Box<dyn Error + Send + Sync + 'static>;
84
85/// A generic [`Error`] wrapper for trace handler errors.
86///
87/// Trace handlers can define their own [`Error`] type which can be seamlessly converted
88/// into this type since it is a [`Box`].
89pub type TraceError = Box<dyn Error + Send + Sync + 'static>;
90
91// EVENT HANDLER REGISTRY
92// ================================================================================================
93
94/// Registry for maintaining event handlers.
95///
96/// # Example
97///
98/// ```rust, ignore
99/// impl Host for MyHost {
100///     fn on_event(
101///         &mut self,
102///         process: &mut ProcessorState,
103///         event_id: u32,
104///     ) -> Result<(), EventError> {
105///         if self
106///             .event_handlers
107///             .handle_event(event_id, process)
108///             .map_err(|err| EventError::HandlerError { id: event_id, err })?
109///         {
110///             // the event was handled by the registered event handlers; just return
111///             return Ok(());
112///         }
113///
114///         // implement custom event handling
115///
116///         Err(EventError::UnhandledEvent { id: event_id })
117///     }
118/// }
119/// ```
120#[derive(Default)]
121pub struct EventHandlerRegistry {
122    handlers: BTreeMap<EventId, (EventName, Arc<dyn EventHandler>)>,
123}
124
125impl EventHandlerRegistry {
126    pub fn new() -> Self {
127        Self { handlers: BTreeMap::new() }
128    }
129
130    /// Registers an [`EventHandler`] with a given event name.
131    ///
132    /// The [`EventId`] is computed from the event name during registration.
133    ///
134    /// # Errors
135    /// Returns an error if:
136    /// - The event is a reserved system event
137    /// - A handler with the same event ID is already registered
138    pub fn register(
139        &mut self,
140        event: EventName,
141        handler: Arc<dyn EventHandler>,
142    ) -> Result<(), ExecutionError> {
143        // Check if the event is a reserved system event
144        if SystemEvent::from_name(event.as_str()).is_some() {
145            return Err(ExecutionError::ReservedEventNamespace { event });
146        }
147
148        // Compute EventId from the event name
149        let id = event.to_event_id();
150        match self.handlers.entry(id) {
151            Entry::Vacant(e) => e.insert((event, handler)),
152            Entry::Occupied(_) => return Err(ExecutionError::DuplicateEventHandler { event }),
153        };
154        Ok(())
155    }
156
157    /// Unregisters a handler with the given identifier, returning a flag whether a handler with
158    /// that identifier was previously registered.
159    pub fn unregister(&mut self, id: EventId) -> bool {
160        self.handlers.remove(&id).is_some()
161    }
162
163    /// Returns the [`EventName`] registered for `id`, if any.
164    pub fn resolve_event(&self, id: EventId) -> Option<&EventName> {
165        self.handlers.get(&id).map(|(event, _)| event)
166    }
167
168    /// Handles the event if the registry contains a handler with the same identifier.
169    ///
170    /// Returns an `Option<_>` indicating whether the event was handled. Returns `None` if the
171    /// event was not handled, `Some(mutations)` if it was handled successfully, and propagates
172    /// handler errors to the caller.
173    pub fn handle_event(
174        &self,
175        id: EventId,
176        process: &ProcessorState,
177    ) -> Result<Option<Vec<AdviceMutation>>, EventError> {
178        if let Some((_event_name, handler)) = self.handlers.get(&id) {
179            let mutations = handler.on_event(process)?;
180            return Ok(Some(mutations));
181        }
182
183        Ok(None)
184    }
185}
186
187impl Debug for EventHandlerRegistry {
188    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189        let events: Vec<_> = self.handlers.values().map(|(event, _)| event).collect();
190        f.debug_struct("EventHandlerRegistry").field("handlers", &events).finish()
191    }
192}
193
194// DEBUG HANDLER
195// ================================================================================================
196
197/// Handler for debug and trace operations
198pub trait DebugHandler: Sync {
199    /// This function is invoked when the `Debug` decorator is executed.
200    fn on_debug(
201        &mut self,
202        process: &ProcessorState,
203        options: &DebugOptions,
204    ) -> Result<(), DebugError> {
205        let mut handler = crate::host::debug::DefaultDebugHandler::default();
206        handler.on_debug(process, options)
207    }
208
209    /// This function is invoked when the `Trace` decorator is executed.
210    fn on_trace(&mut self, process: &ProcessorState, trace_id: u32) -> Result<(), TraceError> {
211        let _ = (&process, trace_id);
212        #[cfg(feature = "std")]
213        std::println!(
214            "Trace with id {} emitted at step {} in context {}",
215            trace_id,
216            process.clock(),
217            process.ctx()
218        );
219        Ok(())
220    }
221}