| Crates.io | forgeconf_macros |
| lib.rs | forgeconf_macros |
| version | 0.2.0 |
| created_at | 2025-11-29 16:56:07.181021+00 |
| updated_at | 2025-11-30 03:31:50.48743+00 |
| description | Procedural macro crate for Forgeconf. |
| homepage | |
| repository | https://github.com/chikof/forgeconf |
| max_upload_size | |
| id | 1957034 |
| size | 33,444 |
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.
#[forgeconf] as well, enabling deeply nested configuration trees without boilerplate.toml, yaml, json).Add Forgeconf to your workspace:
[dependencies]
forgeconf = "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:
[dependencies.forgeconf]
version = "0.1"
default-features = false
features = ["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.
use forgeconf::{forgeconf, ConfigError};
#[forgeconf(config(path = "config/app.toml"))]
struct AppConfig {
#[field(default = 8080)]
port: u16,
#[field(env = "APP_DATABASE_URL")]
database_url: String,
}
fn main() -> Result<(), ConfigError> {
let cfg = AppConfig::loader()
.with_config() // load every `config(...)` entry
.with_cli(200) // merge `--key=value` CLI arguments
.load()?;
println!("listening on {}", cfg.port);
println!("db url: {}", cfg.database_url);
Ok(())
}
#[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) |
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(cli = "...")])#[field(env = "...")])with_cli, with_config, or add_source)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:
fn ensure_https(value: &String, key: &str) -> Result<(), ConfigError> {
if value.starts_with("https://") {
Ok(())
} else {
Err(ConfigError::mismatch(key, "https url", value.clone()))
}
}
#[forgeconf]
struct SecureConfig {
#[field(validate = forgeconf::validators::range(1024, 65535))]
port: u16,
#[field(
validate = ensure_https,
validate = forgeconf::validators::len_range(12, 128),
validate = forgeconf::validators::matches_regex(regex::Regex::new("^https://").unwrap()),
)]
endpoint: String,
}
The most common helpers:
non_empty(), min_len(n), max_len(n), and len_range(min, max) โ work with any type implementing validators::HasLen (Strings, Vecs, maps, sets, โฆ).range(min, max) โ enforce numeric/string bounds via PartialOrd.one_of([..]) โ restrict values to a predefined set.matches_regex(regex::Regex) โ ensure the value matches a regular expression (enable the regex Cargo feature and add the regex crate to your Cargo.toml when using this helper).Each helper returns a closure that you can combine or wrap to build higher-level policies.
The generated <Struct>Loader exposes:
with_config() โ loads every config(...) entry from the attribute.with_cli(priority) โ merges parsed CLI arguments at the provided priority.add_source(source) โ supply any custom ConfigSource.load() โ merges the queued sources and deserializes the struct.You can construct sources manually using items re-exported from the crate:
let cfg = AppConfig::loader()
.add_source(forgeconf::ConfigFile::new("settings.toml"))
.add_source(forgeconf::CliArguments::new().with_args(["--port=9090"]))
.load()?;
| 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.
Forgeconf is released under the MIT License.