coalesced/
lib.rs

1//! coalesced supports reading configs from multiple sources
2//!
3//! # Usage
4//! ```toml
5//! [dependencies]
6//! coalesced = { git = "https://github.com/hayas1/coalesced" }
7//! ```
8//!
9//! # Examples
10//! [`Coalesce::prior`] will return the last confirmed value. [`Coalesce::posterior`] will return the first confirmed value.
11//! | `Config`  | file | env     | cli      | →   | prior    | posterior |
12//! | --------- | ---- | ------- | -------- | --- | -------- | --------- |
13//! | `opt_num` | 10   | 100     |          | →   | 100      | 10        |
14//! | `opt_str` |      | hundred | thousand | →   | thousand | hundred   |
15//! | `boolean` | true | false   | true     | →   | true     | true      |
16//!
17//! ```rust
18//! use coalesced::Coalesce;
19//!
20//! #[derive(Coalesce)]
21//! pub struct Config<'a> {
22//!     opt_num: Option<i32>,
23//!     opt_str: Option<&'a str>,
24//!     #[coalesced(with = coalesced::strategy::Overwrite)]
25//!     boolean: bool
26//! }
27//!
28//! let from_file = Config {
29//!     opt_num: Some(10),
30//!     opt_str: None,
31//!     boolean: true,
32//! };
33//! let from_env = Config {
34//!     opt_num: Some(100),
35//!     opt_str: Some("hundred"),
36//!     boolean: false,
37//! };
38//! let from_cli = Config {
39//!     opt_num: None,
40//!     opt_str: Some("thousand"),
41//!     boolean: true,
42//! };
43//! let config = from_file.prior(from_env).prior(from_cli);
44//! assert!(matches!(config, Config {
45//!     opt_num: Some(100),
46//!     opt_str: Some("thousand"),
47//!     boolean: true,
48//! }));
49//!
50//! let from_file = Config {
51//!     opt_num: Some(10),
52//!     opt_str: None,
53//!     boolean: true,
54//! };
55//! let from_env = Config {
56//!     opt_num: Some(100),
57//!     opt_str: Some("hundred"),
58//!     boolean: false,
59//! };
60//! let from_cli = Config {
61//!     opt_num: None,
62//!     opt_str: Some("thousand"),
63//!     boolean: true,
64//! };
65//! let config = from_file.posterior(from_env).posterior(from_cli);
66//! assert!(matches!(config, Config {
67//!     opt_num: Some(10),
68//!     opt_str: Some("hundred"),
69//!     boolean: true,
70//! }));
71//! ```
72//!
73//! ### Lazy Evaluation
74//! Related to [`crate::Coalesced`]. Lazy evaluation is supported so we can follow the changes until the value is confirmed.
75//! ```
76//! use coalesced::{Coalesce, History, IntoHistory};
77//!
78//! #[derive(Coalesce)]
79//! pub struct Config<'a> {
80//!     opt_num: Option<i32>,
81//!     opt_str: Option<&'a str>,
82//!     #[coalesced(with = coalesced::strategy::Overwrite)]
83//!     boolean: bool,
84//! }
85//!
86//! let from_file = Config {
87//!     opt_num: Some(10),
88//!     opt_str: None,
89//!     boolean: true,
90//! };
91//! let from_env = Config {
92//!     opt_num: Some(100),
93//!     opt_str: Some("hundred"),
94//!     boolean: false,
95//! };
96//! let from_cli = Config {
97//!     opt_num: None,
98//!     opt_str: Some("thousand"),
99//!     boolean: true,
100//! };
101//!
102//! let config = from_file.into_history().prior(from_env).prior(from_cli);
103//! assert!(matches!(
104//!     config.base(),
105//!     Config {
106//!         opt_num: Some(10),
107//!         opt_str: None,
108//!         boolean: true,
109//!     }
110//! ));
111//! assert!(matches!(config.into(), Config {
112//!     opt_num: Some(100),
113//!     opt_str: Some("thousand"),
114//!     boolean: true,
115//! }));
116//! ```
117//!
118//! ### Extensions metadata
119//! Related to [`crate::WithExt`]. Extensions metadata is supported so we can follow the source of the confirmed value.
120//! ```
121//! use coalesced::{Coalesce, Extension};
122//!
123//! #[derive(Coalesce)]
124//! pub struct Config<'a> {
125//!     opt_num: Option<i32>,
126//!     opt_str: Option<&'a str>,
127//!     #[coalesced(with = coalesced::strategy::Overwrite)]
128//!     boolean: bool,
129//! }
130//!
131//! let from_file = Config {
132//!     opt_num: Some(10),
133//!     opt_str: None,
134//!     boolean: true,
135//! };
136//! let from_env = Config {
137//!     opt_num: Some(100),
138//!     opt_str: Some("hundred"),
139//!     boolean: false,
140//! };
141//! let from_cli = Config {
142//!     opt_num: None,
143//!     opt_str: Some("thousand"),
144//!     boolean: true,
145//! };
146//!
147//! let (file, env, cli) = (
148//!     from_file.with_extension(&"file"),
149//!     from_env.with_extension(&"env"),
150//!     from_cli.with_extension(&"cli"),
151//! );
152//!
153//! let config = file.prior(env).prior(cli);
154//! assert_eq!(config.opt_num.extension, &"env");
155//! assert_eq!(config.opt_str.extension, &"cli");
156//! assert_eq!(config.boolean.extension, &"cli");
157//! assert!(matches!(config.into(), Config {
158//!     opt_num: Some(100),
159//!     opt_str: Some("thousand"),
160//!     boolean: true
161//! }));
162//! ```
163//!
164//! # Documents
165//! <https://hayas1.github.io/coalesced/coalesced>
166//!
167//! # Testing
168//! ## Benchmarks
169//! TODO
170//!
171//! ## Coverage
172//! <https://hayas1.github.io/coalesced/coalesced/tarpaulin-report.html>
173//!
174
175pub use coalesced_base::{
176    coalesce::Coalesce,
177    coalesced::{Coalesced, History, IntoHistory},
178    extension::{Extension, WithExt},
179    strategy,
180};
181
182#[cfg(feature = "derive")]
183pub use coalesced_derive::Coalesce;