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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
//! The resolution engine: the thing that folds the collected layers.
//!
//! A load walks its sources itself — discovery, decryption, sections, the
//! environment and the `.env` files are this crate's, and no engine sees a
//! file. What an engine does is the step after that: take one tree per
//! layer, in precedence order, and answer with the merged tree and which
//! layer won each leaf.
//!
//! ```text
//! defaults {host: localhost, port: 5432} tag 0
//! file {host: db.internal} tag 1
//! env {port: 6543} tag 2
//! ──────────── fold ────────────
//! values {host: db.internal, port: 6543}
//! tags host → 1, port → 2
//! ```
//!
//! **Every engine here implements the same rule** — tables descend,
//! everything else replaces, arrays included — so which one is installed is
//! not a question about what a configuration means. That is not a hope: the
//! whole composition corpus, a generated corpus of layer stacks, and the
//! corner cases where a backend's own habits could show through all run
//! through every engine, and both the tree and the winner of every leaf are
//! compared.
//!
//! Where a backend disagrees, the adapter is what gives way. One of them
//! reads a top-level key as a *path expression*, which would turn
//! `{"my.module": "debug"}` into a nested table; its adapter hands over
//! stand-in names and puts the document's own back afterwards. Another
//! records provenance per provider and cannot answer for a key with a dot
//! in it; the fold fills that in from the layers it was given.
//!
//! Two ship:
//!
//! | engine | feature | what it is |
//! |---|---|---|
//! | [`config_rs()`] | — | the fold of the `config` crate; the default |
//! | [`figment()`] | `figment` | the fold of the `figment` crate |
//!
//! A third is anything implementing [`Engine`]: the trait deals in this
//! crate's [`Value`] and in opaque tags, so nothing about a backend reaches
//! it. **This crate keeps no fold of its own** — it wrote one, proved the
//! others against it, and then deleted it rather than maintain a second
//! implementation of somebody else's rule.
use BTreeMap;
use fmt;
use crateError;
use crateValue;
/// One layer, on its way into an engine.
///
/// The tag is opaque and belongs to the caller: hand it back for every leaf
/// this layer wins, and the caller turns it into the file or variable a
/// person reads. An engine that invents a tag it was not given is an engine
/// reporting a source that does not exist.
/// What an engine hands back.
/// A fold, and where each leaf came from.
///
/// Implement this to resolve with something else entirely — a backend this
/// crate does not ship, or a rule of your own. Two things are asked of an
/// implementation, and the rest is its business:
///
/// - **Precedence is the argument's order.** `layers[0]` is the lowest.
/// - **A tag is reported only for a leaf that layer actually supplied.**
///
/// # Errors
///
/// A fold can fail — a backend may refuse a key shape of its own — and the
/// error reaches the caller as an ordinary load failure. It must not carry
/// a configuration value: an engine that puts one in a message breaks the
/// contract every other part of this crate keeps.
/// The [`config`](https://docs.rs/config) crate's fold.
///
/// The default. `config` carries an origin on every value, so a leaf's
/// winner comes back from the backend rather than from a second walk.
/// The [`figment`](https://docs.rs/figment) crate's fold.
///
/// figment records metadata per *provider*, so each layer is merged as its
/// own provider and the winner of a leaf is read back from the metadata
/// that survived the merge.
/// Every engine this build ships, lowest-level first.
///
/// **The one list.** The agreement tests walk it rather than naming
/// engines, so an engine added here is compared against the others on every
/// corpus the crate has without a test being edited — which is the point:
/// an engine that nothing compares is an engine nobody has checked.
///
/// The default comes first, and is the one a disagreement is reported
/// against.
/// The engine a load uses when nothing chose one.
///
/// **This crate has no fold of its own.** It had one, as the reference the
/// others were compared against — and carrying a second implementation of
/// a rule somebody else already implements is maintenance with no reader.
/// The comparison it existed for is between the backends; the rule itself
/// is written down in the book and held by the tests either way.
pub
/// The installed engine, or the default.
pub
static INSTALLED: OnceLock = new;
/// Installs `engine` for every load in this process that does not name one.
///
/// Call it before the first `init()`. A load that names its own engine —
/// `builder(..).engine(..)` — uses that one whatever is installed here.
///
/// # Errors
///
/// If one is already installed. The rejected engine is returned, so a
/// caller can tell "already set" from "failed".
/// Whether an engine has been installed.
// ---------------------------------------------------------------------------
// config-rs
// ---------------------------------------------------------------------------
use crateEngine as ConfigRs;
// ---------------------------------------------------------------------------
// figment
// ---------------------------------------------------------------------------
use crateEngine as Figment;