pub use aristo_macros::{expose_pub, yield_point, Inspect};
use std::cell::Cell;
thread_local! {
static HOOK: Cell<Option<fn(&'static str)>> = const { Cell::new(None) };
}
pub fn set_hook(hook: Option<fn(&'static str)>) {
HOOK.with(|h| h.set(hook));
}
#[doc(hidden)]
pub fn __yield_point(label: &'static str) {
if let Some(hook) = HOOK.with(|h| h.get()) {
hook(label);
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::cell::Cell;
thread_local! {
static OBSERVED: Cell<Option<&'static str>> = const { Cell::new(None) };
}
fn capture(label: &'static str) {
OBSERVED.with(|o| o.set(Some(label)));
}
fn ignore(_: &'static str) {}
#[test]
fn default_is_noop() {
set_hook(None);
__yield_point("noop.label");
}
#[test]
fn hook_receives_label() {
OBSERVED.with(|o| o.set(None));
set_hook(Some(capture));
__yield_point("captured.label");
assert_eq!(OBSERVED.with(|o| o.get()), Some("captured.label"));
set_hook(None);
}
#[test]
fn replacing_hook_invokes_only_the_latest() {
OBSERVED.with(|o| o.set(None));
set_hook(Some(capture));
set_hook(Some(ignore));
__yield_point("ignored.label");
assert_eq!(OBSERVED.with(|o| o.get()), None);
set_hook(None);
}
#[test]
fn clearing_hook_restores_noop() {
OBSERVED.with(|o| o.set(None));
set_hook(Some(capture));
set_hook(None);
__yield_point("after.clear");
assert_eq!(OBSERVED.with(|o| o.get()), None);
}
}