pub fn is_truthy(val: &str) -> bool {
matches!(val.to_lowercase().as_str(), "1" | "true" | "on" | "yes")
}
pub fn is_falsey(val: &str) -> bool {
matches!(val.to_lowercase().as_str(), "0" | "false" | "off" | "no")
}
pub fn parse_bool(val: &str) -> anyhow::Result<bool> {
if is_truthy(val) {
Ok(true)
} else if is_falsey(val) {
Ok(false)
} else {
anyhow::bail!(
"Invalid boolean value: '{}'. Expected one of: true/false, 1/0, on/off, yes/no",
val
)
}
}
pub fn env_is_truthy(env: &str) -> bool {
match std::env::var(env) {
Ok(val) => is_truthy(val.as_str()),
Err(_) => false,
}
}
pub fn env_is_falsey(env: &str) -> bool {
match std::env::var(env) {
Ok(val) => is_falsey(val.as_str()),
Err(_) => false,
}
}
pub fn env_parse_bool(env: &str) -> anyhow::Result<Option<bool>> {
match std::env::var(env) {
Ok(val) => parse_bool(&val).map(Some),
Err(std::env::VarError::NotPresent) => Ok(None),
Err(e) => anyhow::bail!("Failed to read environment variable {}: {}", env, e),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_truthy() {
assert!(is_truthy("1"));
assert!(is_truthy("true"));
assert!(is_truthy("True"));
assert!(is_truthy("TRUE"));
assert!(is_truthy("on"));
assert!(is_truthy("ON"));
assert!(is_truthy("yes"));
assert!(is_truthy("YES"));
assert!(!is_truthy("0"));
assert!(!is_truthy("false"));
assert!(!is_truthy("off"));
assert!(!is_truthy("no"));
assert!(!is_truthy(""));
assert!(!is_truthy("random"));
}
#[test]
fn test_is_falsey() {
assert!(is_falsey("0"));
assert!(is_falsey("false"));
assert!(is_falsey("False"));
assert!(is_falsey("FALSE"));
assert!(is_falsey("off"));
assert!(is_falsey("OFF"));
assert!(is_falsey("no"));
assert!(is_falsey("NO"));
assert!(!is_falsey("1"));
assert!(!is_falsey("true"));
assert!(!is_falsey("on"));
assert!(!is_falsey("yes"));
assert!(!is_falsey(""));
assert!(!is_falsey("random"));
}
#[test]
fn test_env_is_truthy_not_set() {
assert!(!env_is_truthy("DEFINITELY_NOT_SET_VAR_12345"));
}
#[test]
fn test_env_is_falsey_not_set() {
assert!(!env_is_falsey("DEFINITELY_NOT_SET_VAR_12345"));
}
#[test]
fn test_parse_bool() {
assert!(parse_bool("1").unwrap());
assert!(parse_bool("true").unwrap());
assert!(parse_bool("TRUE").unwrap());
assert!(parse_bool("on").unwrap());
assert!(parse_bool("yes").unwrap());
assert!(!parse_bool("0").unwrap());
assert!(!parse_bool("false").unwrap());
assert!(!parse_bool("FALSE").unwrap());
assert!(!parse_bool("off").unwrap());
assert!(!parse_bool("no").unwrap());
assert!(parse_bool("").is_err());
assert!(parse_bool("maybe").is_err());
assert!(parse_bool("2").is_err());
assert!(parse_bool("random").is_err());
}
#[test]
fn test_env_parse_bool_not_set() {
assert_eq!(
env_parse_bool("DEFINITELY_NOT_SET_VAR_12345").unwrap(),
None
);
}
}