Expand description
Layered partial configuration for Rust command-line applications.
Think back to the last time you wrote a command line application that had to be deployed via Docker or some other containerisation service. You need to be able to specify the configuration via the Environment variables, the command line flags, and some configuration file. The basic idea is that if you specify something in the text file, then you want to be able to override it with the environment variables for experimentation.
We can take this further and consider what might happen if we wanted to override some export CONFIGURATION_VARIABLE=something
directive, with the CLI interface, and utilise the fact that
the excellent clap
package provides an intuitive way to
navigate configuration options.
So this pacakge provides you with two traits: HasPartial
and Source
which allow you to do
two things:
-
HasPartial
allows you to declare a structure that you will use as a configuration as having a sister structure that consists of properly handledOption
values for both optional values that might not have to be specified in the same layer, and optional values, not specifying which can reasonably be replaced with a fallback. With thederive
feature enabled, you are able to automatically implement this feature and generate a new structure with the specified name. -
Source
which is used to specify that some object in some way can be used to obtain a layer of configuraiton. For example, with theserde
andtoml
features enabled there is an implementation ofSource
for thepath
-like objects that automatically resolves to a configuration layer for any structure for whichserde::Deserialize
can be automatically derived. We plan to add a custom approach to this, because they way thatserde
handles error reporting is not suitable for configuration files potentially written by humans.
§Examples
§HasPartial
#[derive(partial_config::HasPartial)]
#[partial_derives(Clone)]
#[partial_rename(CustomNameForPartialConfigurationStruct)]
pub struct Configuration {
file_name: String,
port: u16,
configuration_file: Option<String>,
}
This example demonstrates the simplest usage of the derive macro. All it does, is it generates
a new structure which is by default just Partial<NameOfStructType>
but can be changed to
whatever you like via the partial_rename
attribute as seen above. The generated structure can
derive some traits, which is helpful in case writing a manual impl
block is challenging.
The macro recognises the Option<String>
as an optional argument, meaning that if it’s not
present in any layer, it’s just set to None
. It does recognise that port
is not optional,
and if it is not specified in any layer, when the Partial::build
function is invoked, an
error is reported.
As a common courtesy to the users, it’s considered a good idea to report all missing or
malformed configuration options at once, instead of waiting for the user to fix the first
problem and then report the next one. In order to do so, you as the programmer would have to
write a little bit of tedious code, which you get for free by simply deriving HasPartial
on
your type.
Modules§
Structs§
- Missing
Field - A field that is required is not specified in any of the layers. Missing from one layer is not a hard error, and if you need that, you should consider using a different crate.
Enums§
- Error
- All possible things that can go wrong when using
partial_config
.
Traits§
- Config
Path - Implement this trait if you want to indicate that your structure can optionally contain a configuration path.
- HasPartial
- Marker trait that is used to allow a
derive
macro to generate a new structure. This trait is useful for doign some trait-level contraining, but otherwise has no useful data. - Partial
- Implementors of this trait are considered partial states of the full configuration structure
which is
Partial::Target
in this case. If you are implementing this trait manually, pay close attention to the documentation of the provided methods. If your partial structure containsOption
s only and is 1/1 correspondent toPartial::Target
I would recommend either using the [partial_config::HasPartial
] derive macro, or if you want to avoid usingsyn
, to justcargo expand
on the generated code and inline it. - Source
- The implementor of this trait is a source of configuration. The method
Source::to_partial
obtains a single layer of configuration and from a given source.