use super::prelude::*;
use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[non_exhaustive]
pub struct Enabled {}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
enum ThreadState {
Unset,
Set(Option<Enabled>),
}
use ThreadState as TS;
thread_local! {
static ENABLED: Cell<ThreadState> = Cell::new(TS::Unset);
}
fn threadlocal_get() -> ThreadState {
ENABLED.with(|c| c.get())
}
fn threadlocal_set(s: ThreadState) {
ENABLED.with(|c| c.set(s))
}
pub fn with_maybe_enabled<R>(
enabled: Option<Enabled>,
f: impl FnOnce() -> R,
) -> R {
assert_eq!(threadlocal_get(), TS::Unset);
threadlocal_set(TS::Set(enabled));
let r = catch_unwind(AssertUnwindSafe(f));
threadlocal_set(TS::Unset);
match r {
Ok(r) => r,
Err(e) => resume_unwind(e),
}
}
impl Enabled {
pub fn new_for_dd_option(_: Span) -> syn::Result<Self> {
Ok(Enabled {})
}
#[allow(dead_code)] pub fn new_for_syntax(span: Span) -> syn::Result<Self> {
match threadlocal_get() {
TS::Unset => {
Err(span.error("internal error! beta::ENABLED Unset"))
}
TS::Set(ue) => ue.ok_or_else(|| {
span.error(
"beta derive-deftly feature used, without `beta_deftly` template option"
)
}),
}
}
#[cfg(test)]
#[allow(dead_code)]
pub fn test_with_parsing<R>(f: impl FnOnce() -> R) -> R {
with_maybe_enabled(Some(Enabled {}), f)
}
}