Skip to content

Commit

Permalink
feat: env contains list of strings
Browse files Browse the repository at this point in the history
Signed-off-by: simon-an <[email protected]>
  • Loading branch information
simon-an committed Dec 3, 2021
1 parent d27338f commit 4ec2bd6
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 0 deletions.
25 changes: 25 additions & 0 deletions examples/env-list/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use config::Config;
#[derive(Debug, Default, serde_derive::Deserialize, PartialEq)]
struct AppConfig {
list: Vec<String>,
}

fn main() {
std::env::set_var("APP_LIST", "Hello World");

let config = Config::builder()
.add_source(
config::Environment::with_prefix("APP")
.try_parsing(true)
.separator("_")
.list_separator(" "),
)
.build()
.unwrap();

let app: AppConfig = config.try_deserialize().unwrap();

assert_eq!(app.list, vec![String::from("Hello"), String::from("World")]);

std::env::remove_var("APP_LIST");
}
14 changes: 14 additions & 0 deletions src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ pub struct Environment {
/// an environment key of `REDIS_PASSWORD` to match.
separator: Option<String>,

/// Optional character sequence that separates each env value into a vector. only works when try_parsing is set to true
list_separator: Option<String>,

/// Ignore empty env values (treat as unset).
ignore_empty: bool,

Expand Down Expand Up @@ -87,6 +90,11 @@ impl Environment {
self
}

pub fn list_separator(mut self, s: &str) -> Self {
self.list_separator = Some(s.into());
self
}

pub fn ignore_empty(mut self, ignore: bool) -> Self {
self.ignore_empty = ignore;
self
Expand Down Expand Up @@ -155,6 +163,12 @@ impl Source for Environment {
ValueKind::I64(parsed)
} else if let Ok(parsed) = value.parse::<f64>() {
ValueKind::Float(parsed)
} else if let Some(separator) = &self.list_separator {
let v: Vec<Value> = value
.split(separator)
.map(|s| Value::new(Some(&uri), ValueKind::String(s.to_string())))
.collect();
ValueKind::Array(v)
} else {
ValueKind::String(value)
}
Expand Down
36 changes: 36 additions & 0 deletions tests/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,42 @@ fn test_parse_string() {
env::remove_var("STRING_VAL");
}

#[test]
fn test_parse_string_list() {
// using a struct in an enum here to make serde use `deserialize_any`
#[derive(Deserialize, Debug)]
#[serde(tag = "tag")]
enum TestListEnum {
StringList(TestList),
}

#[derive(Deserialize, Debug)]
struct TestList {
string_list: Vec<String>,
}

env::set_var("STRING_LIST", "test string");

let environment = Environment::default().try_parsing(true).list_separator(" ");

let config = Config::builder()
.set_default("tag", "StringList")
.unwrap()
.add_source(environment)
.build()
.unwrap();

let config: TestListEnum = config.try_deserialize().unwrap();

let test_string = vec![String::from("test"), String::from("string")];

match config {
TestListEnum::StringList(TestList { string_list }) => assert_eq!(test_string, string_list),
}

env::remove_var("STRING_LIST");
}

#[test]
fn test_parse_off_string() {
// using a struct in an enum here to make serde use `deserialize_any`
Expand Down

0 comments on commit 4ec2bd6

Please sign in to comment.