Skip to main content

harness_core/
hook.rs

1use crate::{Event, World};
2use serde::{Deserialize, Serialize};
3use std::sync::Arc;
4
5/// What a hook tells the runtime to do after firing.
6#[derive(Debug, Clone, Serialize, Deserialize)]
7#[non_exhaustive]
8pub enum HookOutcome {
9    /// Continue normally.
10    Allow,
11    /// Refuse the action; surface `reason` to the model.
12    Deny { reason: String },
13    /// Replace some part of the event payload (event-specific).
14    Mutate(serde_json::Value),
15    /// Inject text into the active context.
16    Inject(String),
17}
18
19pub trait Hook: Send + Sync + 'static {
20    fn name(&self) -> &str;
21    fn matches(&self, ev: &Event<'_>) -> bool;
22    fn fire(&self, ev: &Event<'_>, world: &mut World) -> HookOutcome;
23}
24
25/// `inventory` slot for compile-time hook registration via `#[hook]`.
26pub struct HookEntry {
27    pub factory: fn() -> Arc<dyn Hook>,
28}
29
30inventory::collect!(HookEntry);
31
32/// Enumerate every `#[hook]`-registered hook.
33pub fn iter_macro_hooks() -> impl Iterator<Item = Arc<dyn Hook>> {
34    inventory::iter::<HookEntry>().map(|e| (e.factory)())
35}