rush_var/
env_source.rs

1use std::collections::{BTreeMap, HashMap};
2
3/// 环境变量查找源 trait。用于支持多种来源的变量查找。
4/// Trait for abstracting environment variable lookup source.
5///
6/// # 用法示例
7/// ```rust
8/// use rush_var::expand_env;
9/// let env = [ ("FOO", "bar") ];
10/// let res = expand_env("$FOO", &env);
11/// assert_eq!(res, "bar");
12/// ```
13pub trait EnvSource {
14    /// 获取指定 key 的变量值,如果不存在则返回 None。
15    fn get(&self, key: &str) -> Option<String>;
16}
17
18/// 为任意已实现 EnvSource 的类型的引用自动实现 EnvSource
19impl<T: EnvSource + ?Sized> EnvSource for &T {
20    fn get(&self, key: &str) -> Option<String> {
21        (**self).get(key)
22    }
23}
24
25/// HashMap 作为环境变量源
26impl EnvSource for HashMap<String, String> {
27    fn get(&self, key: &str) -> Option<String> {
28        self.get(key).cloned()
29    }
30}
31
32/// BTreeMap 作为环境变量源
33impl EnvSource for BTreeMap<String, String> {
34    fn get(&self, key: &str) -> Option<String> {
35        self.get(key).cloned()
36    }
37}
38
39/// 切片 &[(&str, &str)] 作为环境变量源,适用于快速mock和常量环境。
40impl<'a> EnvSource for &'a [(&'a str, &'a str)] {
41    fn get(&self, key: &str) -> Option<String> {
42        self.iter().find(|(k, _)| *k == key).map(|(_, v)| (*v).to_owned())
43    }
44}
45
46/// 系统环境变量(字符串)
47impl EnvSource for std::env::Vars {
48    fn get(&self, key: &str) -> Option<String> {
49        std::env::var(key).ok()
50    }
51}
52
53/// 系统环境变量(OsString)
54impl EnvSource for std::env::VarsOs {
55    fn get(&self, key: &str) -> Option<String> {
56        std::env::var_os(key).and_then(|v| v.into_string().ok())
57    }
58}
59
60/// 闭包适配器,允许以自定义函数/闭包方式提供变量查找逻辑。
61///
62/// # 用法示例
63/// ```rust
64/// use rush_var::env_source::{FnEnvSource};
65/// use rush_var::expand_env;
66/// let env = FnEnvSource(|key: &str| if key == "FOO" { Some("baz".into()) } else { None });
67/// assert_eq!(expand_env("abc$FOO", &env), "abcbaz");
68/// ```
69pub struct FnEnvSource<F>(pub F);
70
71impl<F> EnvSource for FnEnvSource<F>
72where
73    for<'a> F: Fn(&'a str) -> Option<String>,
74{
75    fn get(&self, key: &str) -> Option<String> {
76        self.0(key)
77    }
78}
79
80/// 链式环境变量源:优先查询 primary,没有再查 fallback。
81/// 常用于“临时变量+系统变量”的多层环境方案。
82pub struct EnvSourceChain<A, B> {
83    /// 主查找源(优先)
84    pub primary: A,
85    /// 备选查找源(兜底)
86    pub fallback: B,
87}
88
89impl<A: EnvSource, B: EnvSource> EnvSource for EnvSourceChain<A, B> {
90    fn get(&self, key: &str) -> Option<String> {
91        self.primary.get(key).or_else(|| self.fallback.get(key))
92    }
93}