Forgeconf
Forgeconf is a small attribute macro and runtime for loading configuration files into strongly typed Rust structs. It is built for services that need predictable merge semantics, compile-time validation, and the ability to override values from the command line or the environment without sprinkling glue code throughout the application.
Table of Contents
Highlights
- ๐งฑ Single source of truth โ annotate your struct once and Forgeconf generates the loader, builder, and conversion logic.
- ๐งช Compile-time safety โ missing values or type mismatches become compile errors inside the generated code, so you fail fast during development.
- ๐ Composable sources โ merge any combination of files, CLI flags, and environment variables with explicit priorities.
- ๐งฉ Nested structures โ nested structs can be annotated with
#[forgeconf]as well, enabling deeply nested configuration trees without boilerplate. - ๐งท Format agnostic โ enable just the parsers you need through Cargo features (
toml,yaml,json).
Install
Add Forgeconf to your workspace:
[]
= "0.1"
The crate enables TOML, YAML, and regex-powered validators by default. Add json if you want JSON support, or disable defaults to pick a subset:
[]
= "0.1"
= false
= ["json", "regex"]
Disable regex if you want to skip the regex crate entirely, or re-enable it explicitly (as shown above) when using validators::matches_regex.
Quick start
use ;
Attribute reference
#[forgeconf(...)] accepts zero or more config(...) entries. Each entry takes:
| key | type | description |
|---|---|---|
path |
string (req.) | Relative or absolute path to the file |
format |
"toml" / ... |
Overrides format detection |
priority |
u8 |
Higher numbers win when merging (default 10) |
Field modifiers
Use #[field(...)] on struct fields to fine tune the behaviour:
| option | type | effect |
|---|---|---|
name |
string | Rename the lookup key |
insensitive |
bool | Perform case-insensitive lookups |
env |
string | Pull from an environment variable first |
cli |
string | Check --<cli>=value CLI flags before files |
default |
expression | Fall back to the provided literal/expression |
optional |
bool | Treat Option<T> fields as optional |
validate |
expression | Invoke a validator after parsing (repeatable) |
All lookups resolve in the following order:
- Field-level CLI override (
#[field(cli = "...")]) - Field-level env override (
#[field(env = "...")]) - Sources registered on the loader (
with_cli,with_config, oradd_source)
Validators
Validators are plain expressions that evaluate to something callable with (&T, &str) and returning Result<(), ConfigError>. You can reference free functions, closures, or the helpers under forgeconf::validators:
The most common helpers:
non_empty(),min_len(n),max_len(n), andlen_range(min, max)โ work with any type implementingvalidators::HasLen(Strings, Vecs, maps, sets, โฆ).range(min, max)โ enforce numeric/string bounds viaPartialOrd.one_of([..])โ restrict values to a predefined set.matches_regex(regex::Regex)โ ensure the value matches a regular expression (enable theregexCargo feature and add theregexcrate to yourCargo.tomlwhen using this helper).
Each helper returns a closure that you can combine or wrap to build higher-level policies.
Loader API
The generated <Struct>Loader exposes:
with_config()โ loads everyconfig(...)entry from the attribute.with_cli(priority)โ merges parsed CLI arguments at the provided priority.add_source(source)โ supply any customConfigSource.load()โ merges the queued sources and deserializes the struct.
You can construct sources manually using items re-exported from the crate:
let cfg = loader
.add_source
.add_source
.load?;
Format support
| Feature | Dependency | File extensions |
|---|---|---|
toml |
toml crate |
.toml |
yaml |
yaml-rust2 |
.yml, .yaml |
json |
jzon |
.json |
Each parser lives behind a feature flag. Disable defaults if you want to ship with no parsers enabled.
License
Forgeconf is released under the MIT License.