Expand description
§Overview
The Config derive macro simplifies application configuration by automatically loading
settings from various sources in the following order:
- Environment Variables.
- Configuration File (e.g.,
toml,json,yaml,ini,ron,json5). - Default Values.
§Key Features
- Simplicity: Minimal boilerplate. Define your configuration struct, customize the macro, and you’re good to go.
- Flexibility: Supports a variety of configuration file formats including
toml,json,yaml,ini,ron, andjson5. - Integration: Synergy with other crates, such as
smart_default.
There are also several useful helper attributes for customizing the behavior of the derive macro.
| Attribute | Functionality |
|---|---|
prefix | Sets a prefix for environment variables. Can be applied at the struct or field level. |
path | Specifies the static path to a configuration file. The file extension may (though probably shouldn’t) be omitted. |
env_path | Resolves an environment variable at runtime to determine the configuration file path. |
default_path | Specifies a fallback path used if the path determined by env_path does not exist. |
key | Overrides the default environment variable name. This ignores the prefix and uses the provided key directly. |
name | forwards to #[serde(rename = "_")] to rename fields during serialization/deserialization. It does not affect environment variable names. |
nest | Required for non-standard types which must also derive Config, used for nesting configuration structs. |
skip | Skips loading the attribute from an environment variable. Necessary for types that don’t implement FromStr but are present in the configuration file. |
separator | Specifies a character to separate the prefix and the field name. The default separator is “_”. |
§Path Attribute Behavior
-
env_path: Resolves the provided environment variable into configuration filepath. This takes precedence overpathanddefault_path, but will not panic if the file or environment does not exist. -
path: Directly sets the path to the configuration file. When set,default_pathmay not be used. Panics if the file does not exist. -
default_path: Identical topath, but does not panic if the file does not exist.
§Usage
serde is a required dependency.
[dependencies]
confgr = "0.2.0"
serde = { version = "1.0", features = ["derive"] }Then define your configuration like so:
use confgr::prelude::*;
#[derive(Config)]
#[config(path = "docs.toml", prefix = "APP")]
pub struct AppConfig {
port: u32,
address: String,
#[config(key = "DEBUG_MODE")]
debug: bool,
}
// Default implementation is required.
impl Default for AppConfig {
fn default() -> Self {
Self {
port: 3000,
address: "127.0.0.1".to_string(),
debug: false
}
}
}
std::env::set_var("APP_PORT", "4000");
std::env::set_var("DEBUG_MODE", "true");
let settings = AppConfig::load_config();
assert_eq!(settings.port, 4000);
assert_eq!(settings.address, "127.0.0.1");
assert!(settings.debug)§Warnings/Pitfalls
- Nested structs do not load separate files based on their own
pathattributes. If you would like multiple files to be loaded, you must use multiple structs with multipleload_config()calls. This may change in a future version. - Types that do not implement
FromStrmust use#[config(skip)]or#[config(nest)]. - The
separatorcharacter is only inserted between the prefix and the field name, not in any part of the parsed field name. - The
prefixis applied per field or for the entire struct, but is ignored if#[config(key = "_")]is used. - All configuration structs must implement
Default. - Types used in configuration structs must implement
Deserialize,Clone,DebugandDefault. Optionis not currently compatible with#[config(nest)]on types that implementConfgr.
§Debugging
When encountering issues using the macro, the following methods may be of use.
§Verifying Environment Variables
The get_env_keys() method can be used to retrieve the
resolved environment variable keys based on the struct’s configuration.
use std::collections::HashMap;
use confgr::prelude::*;
#[derive(Config, Default)]
#[config(prefix = "APP")]
pub struct AppConfig {
port: u32,
#[config(separator = "__")]
address: String,
#[config(key = "DEBUG_MODE")]
debug: bool,
}
let keys: HashMap<String, String> = AppConfig::get_env_keys();
assert_eq!(keys["port"], "APP_PORT");
assert_eq!(keys["address"], "APP__ADDRESS");
assert_eq!(keys["debug"], "DEBUG_MODE");§Verifying Configuration File Path
You can use check_file() to ensure that the configuration file
is accessible the path specified or resolved in the path, or env_path attribute.
use confgr::prelude::*;
#[derive(Config, Default)]
#[config(path = "docs.toml", env_path = "APP_CONFIG_FILE")]
pub struct AppConfig {
port: u32,
debug: bool,
}
std::env::set_var("APP_CONFIG_FILE", "env_config.toml");
AppConfig::check_file().expect("Failed to open configuration file.");
std::env::remove_var("APP_CONFIG_FILE");
AppConfig::check_file().expect("Failed to open configuration file.");
§Test Deserialization
The deserialize_from_file() method can be used to manually test the config deserialization step. This
will give you the parsed configuration struct before default values are applied.
use confgr::prelude::*;
#[derive(Config, Default)]
#[config(path = "docs.toml")]
pub struct AppConfig {
port: u32,
debug: bool,
}
let config = AppConfig::deserialize_from_file().expect("Failed to deserialize configuration.");
println!("Deserialized configuration: {:?}", config);
Modules§
- core
- Traits and types consumed by the
Configderive macro. Re-export fromconfgr_core. - derive
- Derive macro for the
Confgrtrait. Re-export fromconfgr_derive. - prelude
- Macro and trait exports for convenience.