Expand description
The ConfigGenerator derive macro is intended to simplify the process of writing configuration loading boilerplate. It currently provides two main features: TOML loading, and loading of values from environment variables.
§Features
By default, the load_toml
feature is enabled, supplying a with_toml
function implementation
on the input struct, and consequently requiring the [serde] and [toml] crates. This feature can
be disabled, and these crates removed, if the user so chooses.
§Usage
The macro is used by applying it to a struct via #[derive(ConfigGenerator)
.
use config_generator::ConfigGenerator;
#[derive(ConfigGenerator, Default)]
struct Config {
#[env_key = "NAME_ENV_KEY"]
pub name: String,
#[env_key = "THREAD_COUNT"]
pub thread_count: u32,
#[env_key = "ALLOWED_ORIGINS"]
pub allowed_origins: Vec<String>,
#[env_key = "ASSETS_PATH"]
pub assets_path: Option<String>,
}
This generates a private struct called Optional[InputStruct]
. Thus, in the example above,
OptionalConfig
would be generated. The generated optional struct is identical to the input
struct except that each of its fields is an Optionwith_toml
or
with_environment
functions to load values.
Note that the user is expected to derive Default or implement some other means of obtaining
a starting point for configuration loading, such as a new
function.
For example, the following basic example loads values from an input toml file.
use config_generator::ConfigGenerator;
#[derive(ConfigGenerator, Default)]
struct Config {
pub name: String,
}
fn main() {
let config = Config::default().with_toml(&"tests/tomls/simple_config.toml");
}
Similarly, the following example would load values from the environment, specifically
from the NAME_KEY
environment variable annotated above the name
field.
use config_generator::ConfigGenerator;
#[derive(ConfigGenerator, Default)]
struct Config {
#[env_key = "NAME_KEY"]
pub name: String,
}
fn main() {
let config = Config::default().with_env();
}
These functions can also be composed together. When composed, a latter-executed function will superimpose loaded values on the prior config.
use config_generator::ConfigGenerator;
#[derive(ConfigGenerator, Default)]
struct Config {
#[env_key = "NAME_KEY"]
pub name: String,
}
fn main() {
let config = Config::default()
.with_toml(&"tests/tomls/simple_config.toml")
.with_env();
}
Superimposing values follows certain rules:
- If the original struct had an Option
field, the value for that field will only be replaced if the new value is Some. A subseqently-loaded None value will not be applied. - If the original struct had a Vec
field, subsequently-loaded values will be combined with prior values, such that the Vec has each new value pushed to the end. - For all other types, if a value is loaded, then that value will replace any previously-set value.