1use std::sync::OnceLock;
2
3use noop::NoopDispatch;
4
5use crate::catalog::CatalogEntry;
6
7pub mod noop;
8pub mod test;
9
10#[cfg(feature = "antithesis")]
11pub mod antithesis;
12
13pub enum Event {
14 RegisterEntry(&'static CatalogEntry),
15 EmitEntry {
16 entry: &'static CatalogEntry,
17 condition: bool,
18 details: serde_json::Value,
19 },
20 SetupComplete {
21 details: serde_json::Value,
22 },
23 Custom {
24 name: &'static str,
25 value: serde_json::Value,
26 },
27}
28
29pub trait Dispatch: Sync + Send {
30 fn emit(&self, event: Event);
31 fn random(&self) -> u64;
32}
33
34static DISPATCHER: OnceLock<&'static dyn Dispatch> = OnceLock::new();
35
36#[derive(Debug)]
37pub struct SetDispatchError;
38
39impl std::error::Error for SetDispatchError {}
40
41impl std::fmt::Display for SetDispatchError {
42 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
43 fmt.write_str("attempted to set the dispatcher after it was already set")
44 }
45}
46
47pub fn set_dispatcher(dispatcher: &'static dyn Dispatch) -> Result<(), SetDispatchError> {
50 DISPATCHER.set(dispatcher).map_err(|_| SetDispatchError)
51}
52
53pub fn dispatcher() -> &'static dyn Dispatch {
57 match DISPATCHER.get() {
58 Some(dispatch) => *dispatch,
59 None => {
60 static NOOP: NoopDispatch = NoopDispatch;
61 &NOOP
62 }
63 }
64}
65
66#[inline]
68pub fn get_random() -> u64 {
69 dispatcher().random()
70}
71
72#[inline]
74pub fn emit(event: Event) {
75 dispatcher().emit(event);
76}