https://github.com/leptonyu/cfg-rs
A Configuration Library for Rust Applications
https://github.com/leptonyu/cfg-rs
config configuration environment json rust settings toml yaml
Last synced: 4 months ago
JSON representation
A Configuration Library for Rust Applications
- Host: GitHub
- URL: https://github.com/leptonyu/cfg-rs
- Owner: leptonyu
- License: mit
- Created: 2021-08-14T13:19:01.000Z (almost 5 years ago)
- Default Branch: main
- Last Pushed: 2025-03-11T02:24:43.000Z (over 1 year ago)
- Last Synced: 2025-03-29T11:11:24.689Z (about 1 year ago)
- Topics: config, configuration, environment, json, rust, settings, toml, yaml
- Language: Rust
- Homepage: https://crates.io/crates/cfg-rs
- Size: 274 KB
- Stars: 39
- Watchers: 2
- Forks: 6
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-rust - leptonyu/cfg-rs - rs](https://crates.io/crates/cfg-rs)] - A Configuration Library for Rust Applications. (Libraries / Configuration)
- awesome-rust - leptonyu/cfg-rs - rs](https://crates.io/crates/cfg-rs)] - A Configuration Library for Rust Applications [](https://github.com/leptonyu/cfg-rs/actions) (Libraries / Configuration)
- fucking-awesome-rust - leptonyu/cfg-rs - rs](crates.io/crates/cfg-rs)] - A Configuration Library for Rust Applications. (Libraries / Configuration)
- awesome-rust-with-stars - leptonyu/cfg-rs - rs) | A Configuration Library for Rust Applications. | 2025-12-02 | (Libraries / Configuration)
README
# cfg-rs: A Configuration Library for Rust Applications
[](https://crates.io/crates/cfg-rs)
[](https://crates.io/crates/cfg-rs)
[](https://docs.rs/cfg-rs)
[](https://deps.rs/crate/cfg-rs)
[](https://github.com/leptonyu/cfg-rs/blob/master/LICENSE)
[](https://github.com/leptonyu/cfg-rs/actions)
[](#minimum-supported-rust-version)
cfg-rs is a lightweight, flexible configuration loader for Rust applications. It composes multiple sources (files, env, inline maps, random, etc.), supports live refresh, placeholder expansion, and derive-based typed configs — all without a serde dependency.
See the [examples](https://github.com/leptonyu/cfg-rs/tree/main/examples) directory for end-to-end demos.
## Features
- Single call to load typed config: see [Configuration::get](struct.Configuration.html#method.get)
- Derive your config types: see [FromConfig](derive.FromConfig.html)
- Default values via field attributes: see [field attributes](derive.FromConfig.html#field-annotation-attribute)
- Placeholder expansion like `${cfg.key}`: see [ConfigValue](enum.ConfigValue.html#placeholder-expression)
- Random values under the `rand` feature (e.g. `configuration.get::("random.u8")`)
- Refreshable values via [RefValue](struct.RefValue.html) and refreshable [Configuration](struct.Configuration.html)
- Pluggable sources with clear priority: see [register_source](struct.Configuration.html#method.register_source)[^priority]
- No serde dependency
[^priority]: Source precedence follows registration order — earlier registrations have higher priority.
## Supported formats and feature flags
Built-in file parsers (enable via Cargo features):
- `toml`: extensions `.toml`, `.tml`
- `yaml`: extensions `.yaml`, `.yml`
- `json`: extension `.json`
- `ini`: extension `.ini`
Other useful features:
- `rand`: random value provider (e.g. `random.u8`, `random.string`)
- `log`: minimal logging integration for value parsing
- `coarsetime`: coarse time helpers for time-related values
- `regex`: regex validation support for `#[validate(regex = ...)]`
## Installation
Add to your Cargo.toml with the features you need:
```toml
[dependencies]
cfg-rs = { version = "^0.6", features = ["toml"] }
```
For a batteries-included setup, use the convenience feature set:
```toml
cfg-rs = { version = "^0.6", features = ["full"] }
```
## Quick start
### 1) One-liner with predefined sources
```rust
use cfg_rs::*;
let configuration = Configuration::with_predefined().unwrap();
// use configuration.get::("your.key") or derive types (see below)
```
See [PredefinedConfigurationBuilder::init](struct.PredefinedConfigurationBuilder.html#method.init) for details.
### 2) Customize predefined builder
```rust,no_run
use cfg_rs::*;
init_cargo_env!();
let configuration = Configuration::with_predefined_builder()
.set_cargo_env(init_cargo_env())
.init()
.unwrap();
```
### 3) Compose your own sources (priority = registration order)
```rust,no_run
use cfg_rs::*;
init_cargo_env!();
let mut configuration = Configuration::new()
// Layer 0: Cargo env source.
.register_source(init_cargo_env()).unwrap()
// Layer 1: Inline key-values.
.register_kv("inline")
.set("hello", "world")
.finish()
.unwrap();
// Layer 2: Random values (feature = "rand").
#[cfg(feature = "rand")]
{
configuration = configuration.register_random().unwrap();
}
// Layer 3: All environment variables with prefix `CFG_`.
configuration = configuration.register_prefix_env("CFG").unwrap();
// Layer 4: File(s) — extension inferred by feature (e.g. yaml).
configuration = configuration.register_file("/conf/app.yaml", true).unwrap();
// Optional: register an inline file content (e.g. TOML) and merge.
#[cfg(feature = "toml")]
{
let toml = inline_source!("app.toml").unwrap();
configuration = configuration.register_source(toml).unwrap();
}
// Finally use it.
// let port: u16 = configuration.get("server.port").unwrap();
```
See [register_kv](struct.Configuration.html#method.register_kv), [register_file](struct.Configuration.html#method.register_file), [register_random](struct.Configuration.html#method.register_random), and [register_prefix_env](struct.Configuration.html#method.register_prefix_env).
### 4) Handy helpers for tests and small apps
- From inline map (macro):
```rust
#[derive(Debug, cfg_rs::FromConfig)]
struct AppCfg { port: u16, host: String }
let cfg: AppCfg = cfg_rs::from_static_map!(AppCfg, {
"port" => "8080",
"host" => "localhost",
});
```
- From environment variables:
```rust
#[derive(Debug, cfg_rs::FromConfig)]
struct AppCfg { port: u16, host: String }
unsafe {
std::env::set_var("CFG_APP_PORT", "8080");
std::env::set_var("CFG_APP_HOST", "localhost");
}
let cfg: AppCfg = cfg_rs::from_env("CFG_APP").unwrap();
```
## Derive typed configs
Implement strong-typed configs via derive:
```rust,no_run
#[derive(Debug, cfg_rs::FromConfig)]
#[config(prefix = "cfg.app")] // optional, implements FromConfigWithPrefix
struct AppCfg {
port: u16, // required
#[config(default = true)]
enabled: bool, // has default value
#[config(name = "ip")] // remap field name
host: String,
}
```
Attributes summary:
- `#[config(prefix = "cfg.app")]` on struct: implement `FromConfigWithPrefix`
- `#[config(name = "...")]` on field: rename field key
- `#[config(default = )]` on field: default value when missing
See the full reference in [derive.FromConfig](derive.FromConfig.html).
## Validation
The derive macro supports field-level validation via `#[validate(...)]`.
The rules are implemented in [src/validate.rs](src/validate.rs) and are
invoked after parsing field values.
Available validators:
- `range(min = , max = )` for comparable values
- `length(min = , max = )` for string/collection/path length
- `not_empty` for any type implementing `ValidateLength`
- `regex = "..."` (feature = `regex`) for regex matching on strings (pattern can be a string literal or `const &str`)
- `custom = "path::to::fn"` for user-defined validation
Note: `cfg(feature = "...")` checks features of your crate, not dependency features. If you want to gate regex/email fields, define a feature in your crate that enables `cfg-rs/regex` (e.g. `regex = ["cfg-rs/regex"]`) and use that feature in `#[cfg(...)]`.
Example:
```rust,no_run
#[cfg(feature = "regex")]
const USER_RE: &str = "^u[a-z]+$";
#[derive(Debug, cfg_rs::FromConfig)]
#[config(prefix = "app")]
struct AppCfg {
#[validate(range(min = 1, max = 65535))]
port: u16,
#[validate(length(min = 1, max = 32))]
name: String,
#[validate(custom = check_threads)]
threads: usize,
#[cfg(feature = "regex")]
#[validate(regex = USER_RE)]
user: String,
}
fn check_threads(v: &usize) -> Result<(), String> {
if *v == 0 {
return Err("threads must be > 0".to_string());
}
Ok(())
}
```
## Placeholders, randoms, and refresh
- Placeholder expansion: use `${some.key}` inside string values; see [ConfigValue](enum.ConfigValue.html#placeholder-expression)
- Random values: under `rand`, keys like `random.u8`, `random.string` provide per-read randoms
- Refreshing: `Configuration::refresh()` re-reads sources that allow refresh; `RefValue` updates on refresh
## Examples
Browse runnable examples covering common patterns:
- `simple`: minimal setup (full feature set)
- `profile`: working with profiles (requires `toml`)
- `watch`: basic file watching and refresh (requires `yaml`)
- `refresh`: manual refresh and `RefValue`
- `logger`: logging integration (requires `full`)
- `thread_pool`, `salak`, `test_suit`: larger samples and integrations
https://github.com/leptonyu/cfg-rs/tree/main/examples
## License
MIT © contributors. See [LICENSE](https://github.com/leptonyu/cfg-rs/blob/main/LICENSE).
## Minimum supported Rust version
This crate supports Rust **1.85** and newer. Older Rust versions are not guaranteed to compile or be tested.
## Tips and notes
- Source priority is deterministic: earlier registrations override later ones[^priority]
- This crate intentionally does not depend on serde
- Docs.rs builds enable all features for a comprehensive reference