- Vector merging – For
Vec<T>fields the default merge strategy isappend, meaning that values from the configuration file appear first, then environment variables and finally CLI arguments. Usemerge_strategy = "append"explicitly for clarity. When overrides should discard earlier layers entirely (for example, to replace a default list with a CLI-provided value) applymerge_strategy = "replace"instead. -
Map merging – Map fields (such as
BTreeMap<String, _>) default to keyed merges, where later layers update only the entries they define. Applymerge_strategy = "replace"when later layers must replace the entire map. The hello_world example exposes agreeting_templatesmap that uses this strategy, so declarative configuration files can swap the full template set at once. -
Option<T> fields – Fields of type
Option<T>are not treated as required. They default toNoneand can be set via any source. Required CLI arguments can be represented asOption<T>to allow configuration defaults while still requiring the CLI to provide a value when defaults are absent; see thevkexample above. -
Changing naming conventions – Currently, only the default snake/hyphenated (underscores → hyphens)/upper snake mappings are supported. Future versions may introduce attributes such as
file_keyorenvto customize names further. -
Testing – Because the CLI and environment variables are merged at runtime, integration tests should set environment variables and construct CLI argument vectors to exercise the merge logic. The
figmentcrate makes it easy to inject additional providers when writing unit tests. -
Sanitized providers – The
sanitized_providerhelper returns aFigmentprovider withNonefields removed. It aids manual layering when bypassing the derive macro. For example:
use figment::{Figment, providers::Serialized};
use ortho_config::sanitized_provider;
let fig = Figment::from(Serialized::defaults(&Defaults::default()))
.merge(sanitized_provider(&cli)?);
let cfg: Defaults = fig.extract()?;