1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use HashSet;
use StrNode;
use crate::;
/// Reads configuration values from process environment variables.
///
/// All variables starting with `<prefix>_` are read once, when the source is
/// created, so later changes to the process environment never reach the
/// config, not even when it is built again. They are
/// collected into a tree that is then handed to serde for deserialization. Each `__` in the remainder of the
/// variable name introduces a nested level; the resulting segments are
/// lowercased to match partial-struct field names.
///
/// Every value is kept as the raw string and converted to whatever type the
/// target field asks for:
///
/// - `String` (and `&str`, `char`, unit enum variants) get the value
/// verbatim. `123456`, `true`, `null` and `"quoted"` all arrive unchanged.
/// - Numeric and `bool` fields parse the value (`8000`, `-1`, `0.5`, `true`).
/// A value that does not parse is a deserialize error naming the value and
/// the expected type.
/// - `Option<T>` fields are `Some` as soon as the variable is set, with the
/// value converted as `T`: `Option<String>` gets the raw string (`null`
/// included), `Option<u16>` parses it. An env var cannot set an option to
/// `None`; leave the variable unset to fall back to lower layers instead.
/// - Self-describing deserialization (`deserialize_any`, used by
/// `#[serde(untagged)]` and `#[serde(flatten)]`) sees a string.
///
/// Use [`Self::with_list_keys`] to tell the source which dotted paths should
/// be split on `,`. This is required for CSV-encoded list fields like
/// `Vec<String>`; each element is then converted like a single value, so
/// `Vec<u16>` works as well.
///
/// ```
/// use provcfg::{Category, Config, Configurable};
/// use provcfg::sources::EnvSource;
///
/// # #[derive(Configurable, serde::Deserialize, Clone, Default)]
/// # struct Settings {
/// # host: String,
/// # #[configurable(nested)]
/// # database: Database,
/// # }
/// # #[derive(Configurable, serde::Deserialize, Clone, Default)]
/// # struct Database { port: u16 }
/// # unsafe {
/// # std::env::set_var("DEMO_HOST", "db.internal");
/// # std::env::set_var("DEMO_DATABASE__PORT", "5432");
/// # }
/// // `DEMO_HOST` sets `host`; `DEMO_DATABASE__PORT` sets the nested `database.port`.
/// let settings = Config::new()
/// .add_source(EnvSource::new("env", "DEMO"))
/// .build::<SettingsProv>()
/// .unwrap();
///
/// assert_eq!(settings.host.value(), "db.internal");
/// assert_eq!(settings.database.port.value(), &5432);
/// assert_eq!(settings.database.port.source().category(), Category::Env);
/// ```