Skip to main content

rullst_core/feature/
env.rs

1use async_trait::async_trait;
2
3use super::driver::FeatureDriver;
4use super::resolvers::parse_feature_string_value;
5
6// ─── Env Driver ─────────────────────────────────────────────────────────────
7
8/// Driver that parses feature flags defined in environment variables.
9///
10/// Prefix variable names with `FEATURE_` (e.g. `FEATURE_NEW_UI=true`).
11#[non_exhaustive]
12pub struct EnvFeatureDriver;
13
14impl EnvFeatureDriver {
15    /// Creates a new `EnvFeatureDriver`.
16    pub fn new() -> Self {
17        Self
18    }
19
20    fn env_key(flag: &str) -> String {
21        format!("FEATURE_{}", flag.to_uppercase().replace('-', "_"))
22    }
23
24    fn parse_env_value(&self, value: &str, flag: &str, identifier: Option<&str>) -> Option<String> {
25        parse_feature_string_value(value, flag, identifier)
26    }
27}
28
29impl Default for EnvFeatureDriver {
30    fn default() -> Self {
31        Self::new()
32    }
33}
34
35#[async_trait]
36impl FeatureDriver for EnvFeatureDriver {
37    #[cfg_attr(mutants, mutants::skip)]
38    async fn enabled(&self, flag: &str) -> Option<bool> {
39        let key = Self::env_key(flag);
40        let val = std::env::var(key).ok()?;
41        let parsed = self.parse_env_value(&val, flag, None)?;
42        Some(parsed == "enabled")
43    }
44
45    async fn enabled_for(&self, flag: &str, identifier: &str) -> Option<bool> {
46        let key = Self::env_key(flag);
47        let val = std::env::var(key).ok()?;
48        let parsed = self.parse_env_value(&val, flag, Some(identifier))?;
49        Some(parsed == "enabled")
50    }
51
52    async fn variant(&self, flag: &str, identifier: &str) -> Option<String> {
53        let key = Self::env_key(flag);
54        let val = std::env::var(key).ok()?;
55        self.parse_env_value(&val, flag, Some(identifier))
56    }
57}