const TRUTHY: [&str; 4] = ["1", "true", "yes", "on"];
pub fn is_truthy(value: &str) -> bool {
let norm = value.trim().to_ascii_lowercase();
TRUTHY.contains(&norm.as_str())
}
pub fn env_truthy(key: &str) -> bool {
env_truthy_or(key, false)
}
pub fn env_truthy_or(key: &str, default: bool) -> bool {
env_truthy_in(key, default, |k| std::env::var(k).ok())
}
pub fn env_truthy_in(key: &str, default: bool, getter: impl Fn(&str) -> Option<String>) -> bool {
match getter(key) {
Some(raw) => {
let norm = raw.trim();
if norm.is_empty() {
default
} else {
is_truthy(norm)
}
}
None => default,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_truthy_table() {
for v in [
"1", "true", "TRUE", "True", "yes", "YES", "on", "ON", " on ", "\tTrue\n",
] {
assert!(is_truthy(v), "{v:?} 应判定为真");
}
for v in [
"0", "false", "FALSE", "off", "no", "n", "", " ", "2", "enable", "y", "t",
] {
assert!(!is_truthy(v), "{v:?} 应判定为假");
}
}
#[test]
fn test_env_truthy_unset_uses_default() {
let key = "A2C_SMCP_ENV_TRUTHY_DEFINITELY_UNSET_VAR_XYZ";
assert!(!env_truthy(key)); assert!(!env_truthy_or(key, false));
assert!(env_truthy_or(key, true)); }
#[test]
fn test_env_truthy_in_injected_states() {
fn env(k: &str) -> Option<String> {
match k {
"T" => Some("on".to_string()), "F" => Some("0".to_string()), "OFF" => Some(" OFF ".to_string()), "BLANK" => Some(" ".to_string()), _ => None, }
}
assert!(env_truthy_in("T", false, env)); assert!(!env_truthy_in("F", true, env)); assert!(!env_truthy_in("OFF", true, env)); assert!(env_truthy_in("BLANK", true, env)); assert!(!env_truthy_in("BLANK", false, env));
assert!(!env_truthy_in("MISSING", false, env)); assert!(env_truthy_in("MISSING", true, env));
}
}