5 releases
0.2.1 | Aug 3, 2020 |
---|---|
0.2.0 | Aug 3, 2020 |
0.1.2 | Aug 2, 2020 |
0.1.1 | Aug 2, 2020 |
0.1.0 | Aug 2, 2020 |
#430 in Configuration
30KB
627 lines
manaconf
A library for creating a layered configuration provider
This library gives you the ability to setup to read configuration to read from multiple sources, and pull values from these sources via a key.
Inspired by dotnetcore configuration system. (Though this is no where near as deep)
// create our config to read configuration values from environment variables
// with the prefix MYAPP
let config = Builder::new()
.with_source(sources::EnvVarSource::with_prefix("MYAPP"))
.build();
// Read our config data in
let config_data: ConfigData = config.bind()?;
struct ConfigData {
important_value: String,
optional_value: Option<i32>
}
impl TryFromValueRead for ConfigData {
fn try_from<R>(read: &R) -> Result<Self, TryFromValueReadError> {
// As our config is set to read from the environment varibles only
// the EnvVarSource will turn this key into `MYAPP_IMPORTANT` due
// to the prefix set above and the key being requested here
let important_value: String = read.get_expected_value("important")?;
// and this one will be turned into `MYAPP_OPTIONAL`
let optional_value: Option<i32> = read.get_value("optional")?;
ConfigData {
important_value,
optional_value
}
}
}
Keys
Keys are a heirachy represented as a string, i.e. section::subsection::value
,
which can be used to drill down into configurations that may have an arbitary
depth of value organization.
Different sources may interpret this heirachy in different ways. For example
the EnvVarSource
will just turn this into an uppercased string, where the
seperators are replaced with underscores. (SECTION_SUBSECTION_VALUE
).
But a json source might use this as a way to drill down into sub objects.
Sections
You can call the section
method on both Config
and Section
types to create
a section
. As section is simply a pre-applied prefix to your key.
Useful when some code would not or should not be aware of the parent heirachy.
For example, if we took our type above, but in fact our values important
and
optional
actually didn't sit at the root but was instead at some::subsection
we can use Section
to give that code access to values as if the Section
's
prefix was the root.
let section = config.section("some::subsection");
let config_data: ConfigData = section.bind();
// Even though ConfigData only asks for `important` and `optional` due to the
// `Section`, the actual keys being looked up is `some::subsection::important` and
// `some::subsection::optional`.
Multiple sources
You can configure multiple sources by calling Builder::add_source
or
Builder::add_source_with_prefix
when building your Config
.
The order you add your sources is the priority of the sources. The first source being the highest priority.
manaconf will check through each source in order when looking up a value, and
return the first value or error it encounters. If no value is returned by any
source then a None
is returned.
This allows you to configure sources such that you allow one source to override another.
TODO
-
More sources
At current there's only
EnvVarSource
for pulling values from environment variables andCommandLineSource
for pulling from a simplified command line parameter scheme.However I'd like to provide much more than that. Such as toml/json/yml files, .env files and the like.
However, I'm thinking it'd be best to implement other sources as crates.
-
Derive macro
It'd be nice if
TryFromValueRead
could be implemented as a derive macro, though I've not looked into how to do this yet. -
Async support
Might be worth having async support for reading from sources
-
???
We'll see what else falls out with usage