Skip to main content

khive_types/
env.rs

1//! Small environment readers for parsed defaults and explicit boolean flags.
2//!
3//! These helpers do not emit configuration audit events or apply caller-specific
4//! range constraints. Presence-only flags and non-Unicode-sensitive policies
5//! need their existing readers.
6
7use std::str::FromStr;
8use std::sync::OnceLock;
9
10/// Read once and parse the exact Unicode value, without trimming or caching.
11///
12/// Missing, non-Unicode and unparseable values use `default`. Values accepted
13/// by `T::from_str`, including non-finite floats, need any caller-specific checks.
14pub fn env_parse_or<T: FromStr>(name: &str, default: T) -> T {
15    std::env::var(name)
16        .ok()
17        .and_then(|value| value.parse().ok())
18        .unwrap_or(default)
19}
20
21/// Read a trimmed, ASCII-case-insensitive explicit boolean flag.
22///
23/// `1`, `true`, `yes` and `on` enable; `0`, `false`, `no` and `off` disable.
24/// Missing, non-Unicode and unrecognized values use `default`.
25pub fn env_flag(name: &str, default: bool) -> bool {
26    std::env::var(name)
27        .ok()
28        .map(|value| match value.trim().to_ascii_lowercase().as_str() {
29            "1" | "true" | "yes" | "on" => true,
30            "0" | "false" | "no" | "off" => false,
31            _ => default,
32        })
33        .unwrap_or(default)
34}
35
36/// Resolve an explicit flag once using the caller's process-lifetime cell.
37///
38/// Dedicate each cell to one setting. The first initialization fixes its value;
39/// later changes to the environment, name or default do not replace that value.
40/// Callers that require a configuration audit event must retain that policy.
41pub fn cached_env_flag(name: &str, default: bool, cache: &'static OnceLock<bool>) -> bool {
42    *cache.get_or_init(|| env_flag(name, default))
43}