use std::sync::OnceLock;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
pub enum TraceLevel {
#[default]
Off,
Samples,
Gestures,
All,
}
static LEVEL: OnceLock<TraceLevel> = OnceLock::new();
fn parse_level(raw: &str) -> TraceLevel {
match raw.trim().to_ascii_lowercase().as_str() {
"samples" | "sample" => TraceLevel::Samples,
"gestures" | "gesture" => TraceLevel::Gestures,
"all" | "1" | "true" => TraceLevel::All,
_ => TraceLevel::Off,
}
}
pub fn trace_level() -> TraceLevel {
*LEVEL.get_or_init(|| {
std::env::var("TEKSILO_TRACE_INPUT")
.ok()
.map(|raw| parse_level(&raw))
.unwrap_or_default()
})
}
pub fn trace_enabled(level: TraceLevel) -> bool {
match (trace_level(), level) {
(TraceLevel::Off, _) | (_, TraceLevel::Off) => false,
(TraceLevel::All, _) => true,
(active, wanted) => active == wanted,
}
}
#[macro_export]
macro_rules! trace_input {
($level:ident, $($arg:tt)*) => {
if $crate::pointer::trace::trace_enabled($crate::pointer::trace::TraceLevel::$level) {
eprintln!("[teksilo input] {}", format_args!($($arg)*));
}
};
}
#[cfg(test)]
mod tests {
use super::*;
use std::cell::Cell;
#[test]
fn levels_parse_leniently_and_fail_closed() {
assert_eq!(parse_level("samples"), TraceLevel::Samples);
assert_eq!(parse_level(" SAMPLES "), TraceLevel::Samples);
assert_eq!(parse_level("gesture"), TraceLevel::Gestures);
assert_eq!(parse_level("all"), TraceLevel::All);
assert_eq!(parse_level("verbose"), TraceLevel::Off);
assert_eq!(parse_level(""), TraceLevel::Off);
}
#[test]
fn off_is_the_default() {
assert_eq!(TraceLevel::default(), TraceLevel::Off);
}
#[test]
fn tracing_off_does_not_evaluate_its_arguments() {
assert_eq!(
trace_level(),
TraceLevel::Off,
"the suite must run with TEKSILO_TRACE_INPUT unset"
);
let evaluated = Cell::new(0u32);
let bump = || {
evaluated.set(evaluated.get() + 1);
"argument"
};
trace_input!(Samples, "{}", bump());
trace_input!(Gestures, "{} {}", bump(), bump());
assert_eq!(
evaluated.get(),
0,
"arguments must be guarded, not formatted"
);
}
#[test]
fn asking_for_off_is_never_enabled() {
assert!(!trace_enabled(TraceLevel::Off));
}
}