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}