diff --git a/src/providers/env.rs b/src/providers/env.rs index 4ab8ac6..95188f0 100644 --- a/src/providers/env.rs +++ b/src/providers/env.rs @@ -1,7 +1,7 @@ use std::fmt; use crate::{Profile, Provider, Metadata}; -use crate::coalesce::Coalescible; +use crate::coalesce::{Coalescible, Order}; use crate::value::{Map, Dict}; use crate::error::Error; use crate::util::nest; @@ -375,24 +375,34 @@ impl Env { /// struct Config { /// foo: Foo, /// map: Dict, + /// array: Vec, /// } /// /// Jail::expect_with(|jail| { /// // Without splitting: using structured data. /// jail.set_env("APP_FOO", "{key=10}"); /// jail.set_env("APP_MAP", "{one=1,two=2.0}"); + /// jail.set_env("APP_ARRAY", "[1,2,3]"); /// /// let config: Config = Figment::from(Env::prefixed("APP_")).extract()?; /// assert_eq!(config, Config { /// foo: Foo { key: 10 }, /// map: map!["one".into() => 1u8.into(), "two".into() => 2.0.into()], + /// array: vec![1, 2, 3], /// }); /// + /// jail.clear_env(); + /// /// // With splitting. /// jail.set_env("APP_FOO_KEY", 20); /// jail.set_env("APP_MAP_ONE", "1.0"); /// jail.set_env("APP_MAP_TWO", "dos"); /// + /// // Note that array order currently depends on definition order + /// jail.set_env("APP_ARRAY_0", "4"); + /// jail.set_env("APP_ARRAY_2", "5"); + /// jail.set_env("APP_ARRAY_1", "6"); + /// /// let config: Config = Figment::new() /// .merge(Env::prefixed("APP_").split("_")) /// .extract()?; @@ -400,6 +410,7 @@ impl Env { /// assert_eq!(config, Config { /// foo: Foo { key: 20 }, /// map: map!["one".into() => 1.0.into(), "two".into() => "dos".into()], + /// array: vec![4, 5, 6], /// }); /// /// Ok(()) @@ -617,7 +628,7 @@ impl Provider for Env { .into_dict() .expect("key is non-empty: must have dict"); - dict = dict.merge(nested_dict); + dict = dict.coalesce(nested_dict, Order::Admerge); } Ok(self.profile.collect(dict)) diff --git a/src/util.rs b/src/util.rs index 13b0930..971091c 100644 --- a/src/util.rs +++ b/src/util.rs @@ -271,6 +271,13 @@ use crate::value::{Value, Dict}; pub fn nest(key: &str, value: Value) -> Value { fn value_from(mut keys: std::str::Split<'_, char>, value: Value) -> Value { match keys.next() { + Some(k) if k.parse::().is_ok() => { + // TODO + // even if we do honor the index, it will get lost when coalescing. + // seems to me that nesting arrays will only be truly useful when + // coalescing two array items by their index is possible. + Value::from(vec![value_from(keys, value)]) + } Some(k) if !k.is_empty() => { let mut dict = Dict::new(); dict.insert(k.into(), value_from(keys, value));