Runtime Loading
English | 中文 | 日本語 | 한국어 | Français | Deutsch | Español | Português | Svenska | Suomi | Nederlands
Runtime loading is intentionally split between Figment and confique:
figment:
runtime file loading
runtime environment loading
runtime source metadata
confique:
schema metadata
defaults
validation
config templates
The main API is:
#![allow(unused)]
fn main() {
use rust_config_tree::load_config;
let config = load_config::<AppConfig>("config.yaml")?;
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}
Use load_config_with_figment when the application needs source metadata:
#![allow(unused)]
fn main() {
use rust_config_tree::load_config_with_figment;
let (config, figment) = load_config_with_figment::<AppConfig>("config.yaml")?;
let _ = (config, figment);
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}
Loading Steps
The high-level loader performs these steps:
- Resolve the root config path lexically.
- Load the first
.envfile found by walking upward from the root config directory. - Load each config file as a partial layer to discover includes.
- Build a Figment graph from the discovered config files.
- Merge the
ConfiqueEnvProviderwith higher priority than files. - Optionally merge application-specific CLI overrides.
- Extract a
confiquelayer from Figment. - Apply
confiquecode defaults. - Validate and construct the final schema.
load_config and load_config_with_figment perform steps 1-5 and 7-9.
Step 6 is application-specific because this crate cannot infer how a CLI flag
maps to a schema field.
File Formats
The runtime file provider is selected from the config path extension:
.yamland.ymluse YAML..tomluses TOML..jsonand.json5use JSON.- unknown or missing extensions use YAML.
Template generation still uses confique’s template renderers for YAML, TOML, and JSON5-compatible output.
Include Priority
The high-level loader merges file providers so included files are lower priority than the file that included them. The root config file has the highest file priority.
Environment variables have higher priority than all config files. confique
defaults are only used for values that are not supplied by runtime providers.
When CLI overrides are merged after build_config_figment, the full precedence
is:
command-line overrides
> environment variables
> config files
> confique code defaults
The command-line syntax is not defined by rust-config-tree. A flag like
--server-port can override server.port if the application maps that parsed
value into a nested serialized provider. A dotted --server.port or a.b.c
syntax only exists if the application implements it.
This means CLI precedence applies only to keys present in the application’s override provider. Use it for operational values that are frequently changed for a single run. Leave durable configuration in files.
#![allow(unused)]
fn main() {
use figment::providers::Serialized;
use serde::Serialize;
use rust_config_tree::{build_config_figment, load_config_from_figment};
#[derive(Debug, Serialize)]
struct CliOverrides {
#[serde(skip_serializing_if = "Option::is_none")]
server: Option<CliServerOverrides>,
}
#[derive(Debug, Serialize)]
struct CliServerOverrides {
#[serde(skip_serializing_if = "Option::is_none")]
port: Option<u16>,
}
let cli_overrides = CliOverrides {
server: Some(CliServerOverrides { port: Some(9000) }),
};
let figment = build_config_figment::<AppConfig>("config.yaml")?
.merge(Serialized::defaults(cli_overrides));
let config = load_config_from_figment::<AppConfig>(&figment)?;
let _ = config;
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}