pub(crate) fn positive<T: std::str::FromStr + Default + PartialOrd>(v: &str) -> Option<T> {
v.parse::<T>().ok().filter(|n| *n > T::default())
}
pub(crate) fn flag(v: &str) -> Option<bool> {
match v.to_ascii_lowercase().as_str() {
"" | "0" | "false" | "no" => Some(false),
"1" | "true" | "yes" => Some(true),
_ => None,
}
}
fn read<T>(name: &str, raw: Option<&str>, default: T, rule: impl Fn(&str) -> Option<T>, what: &str) -> T {
match raw {
None => default,
Some(raw) => rule(raw).unwrap_or_else(|| panic!("{name}={raw:?} is not {what}")),
}
}
pub fn env_num<T: std::str::FromStr + Default + PartialOrd>(name: &str, default: T) -> T {
let raw = std::env::var(name).ok();
read(name, raw.as_deref(), default, positive, "a positive integer")
}
pub fn env_flag(name: &str, default: bool) -> bool {
let raw = std::env::var(name).ok();
read(name, raw.as_deref(), default, flag, "a boolean (0|1|true|false|yes|no)")
}
#[cfg(test)]
#[path = "tests/env.rs"]
mod tests;