diff options
-rw-r--r-- | src/builder.rs | 22 | ||||
-rw-r--r-- | src/env.rs | 14 | ||||
-rw-r--r-- | tests/env.rs | 21 |
3 files changed, 54 insertions, 3 deletions
diff --git a/src/builder.rs b/src/builder.rs index 018713c..6f928c6 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -11,7 +11,7 @@ use crate::{config::Config, path::Expression, source::Source, value::Value}; /// It registers ordered sources of configuration to later build consistent [`Config`] from them. /// Configuration sources it defines are defaults, [`Source`]s and overrides. /// -/// Defaults are alaways loaded first and can be overwritten by any of two other sources. +/// Defaults are always loaded first and can be overwritten by any of two other sources. /// Overrides are always loaded last, thus cannot be overridden. /// Both can be only set explicitly key by key in code /// using [`set_default`](Self::set_default) or [`set_override`](Self::set_override). @@ -173,6 +173,26 @@ impl<St: BuilderState> ConfigBuilder<St> { .insert(Expression::from_str(key.as_ref())?, value.into()); Ok(self) } + + /// Sets an override if value is Some(_) + /// + /// This function sets an overwrite value if Some(_) is passed. If None is passed, this function does nothing. + /// It will not be altered by any default, [`Source`] nor [`AsyncSource`] + /// + /// # Errors + /// + /// Fails if `Expression::from_str(key)` fails. + pub fn set_override_option<S, T>(mut self, key: S, value: Option<T>) -> Result<Self> + where + S: AsRef<str>, + T: Into<Value>, + { + if let Some(value) = value { + self.overrides + .insert(Expression::from_str(key.as_ref())?, value.into()); + } + Ok(self) + } } impl ConfigBuilder<DefaultState> { @@ -37,6 +37,9 @@ pub struct Environment { /// Parses booleans, integers and floats if they're detected (can be safely parsed). try_parsing: bool, + // Preserve the prefix while parsing + keep_prefix: bool, + /// Alternate source for the environment. This can be used when you want to test your own code /// using this source, without the need to change the actual system environment variables. /// @@ -136,6 +139,11 @@ impl Environment { self } + pub fn keep_prefix(mut self, keep: bool) -> Self { + self.keep_prefix = keep; + self + } + pub fn source(mut self, source: Option<Map<String, String>>) -> Self { self.source = source; self @@ -175,8 +183,10 @@ impl Source for Environment { // Check for prefix if let Some(ref prefix_pattern) = prefix_pattern { if key.starts_with(prefix_pattern) { - // Remove this prefix from the key - key = key[prefix_pattern.len()..].to_string(); + if !self.keep_prefix { + // Remove this prefix from the key + key = key[prefix_pattern.len()..].to_string(); + } } else { // Skip this key return; diff --git a/tests/env.rs b/tests/env.rs index fcadf81..166a83f 100644 --- a/tests/env.rs +++ b/tests/env.rs @@ -75,6 +75,27 @@ fn test_empty_value_is_ignored() { } #[test] +fn test_keep_prefix() { + env::set_var("C_A_B", ""); + + // Do not keep the prefix + let environment = Environment::with_prefix("C"); + + assert!(environment.collect().unwrap().contains_key("a_b")); + + let environment = Environment::with_prefix("C").keep_prefix(false); + + assert!(environment.collect().unwrap().contains_key("a_b")); + + // Keep the prefix + let environment = Environment::with_prefix("C").keep_prefix(true); + + assert!(environment.collect().unwrap().contains_key("c_a_b")); + + env::remove_var("C_A_B"); +} + +#[test] fn test_custom_separator_behavior() { env::set_var("C.B.A", "abc"); |