use std::sync::OnceLock;
const ENV_VAR: &str = "XYBRID_TELEMETRY_OPTOUT";
static OPTED_OUT: OnceLock<bool> = OnceLock::new();
pub fn is_telemetry_opted_out() -> bool {
*OPTED_OUT.get_or_init(|| parse_optout(std::env::var(ENV_VAR).ok().as_deref()))
}
fn parse_optout(value: Option<&str>) -> bool {
matches!(
value.map(|v| v.trim().to_ascii_lowercase()).as_deref(),
Some("1") | Some("true") | Some("yes")
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_unset_returns_false() {
assert!(!parse_optout(None));
}
#[test]
fn parse_truthy_values_return_true() {
assert!(parse_optout(Some("1")));
assert!(parse_optout(Some("true")));
assert!(parse_optout(Some("TRUE")));
assert!(parse_optout(Some("True")));
assert!(parse_optout(Some("yes")));
assert!(parse_optout(Some("YES")));
assert!(parse_optout(Some("Yes")));
}
#[test]
fn parse_truthy_values_tolerate_surrounding_whitespace() {
assert!(parse_optout(Some(" 1 ")));
assert!(parse_optout(Some("\ttrue\n")));
}
#[test]
fn parse_falsy_values_return_false() {
assert!(!parse_optout(Some("")));
assert!(!parse_optout(Some("0")));
assert!(!parse_optout(Some("false")));
assert!(!parse_optout(Some("FALSE")));
assert!(!parse_optout(Some("no")));
assert!(!parse_optout(Some("off")));
assert!(!parse_optout(Some("anything-else")));
}
#[test]
fn cached_value_ignores_mid_process_env_changes() {
let initial = is_telemetry_opted_out();
let prev = std::env::var(ENV_VAR).ok();
let toggle = if initial { "" } else { "1" };
std::env::set_var(ENV_VAR, toggle);
let after_change = is_telemetry_opted_out();
match prev {
Some(v) => std::env::set_var(ENV_VAR, v),
None => std::env::remove_var(ENV_VAR),
}
assert_eq!(
initial, after_change,
"cache must not observe mid-process env changes"
);
}
}