Skip to main content

Crate cfg_rs

Crate cfg_rs 

Source
Expand description

§cfg-rs: A Configuration Library for Rust Applications

Crates.io Crates.io Documentation dependency status License Actions Status 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 directory for end-to-end demos.

§Features

§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:

[dependencies]
cfg-rs = { version = "^0.6", features = ["toml"] }

For a batteries-included setup, use the convenience feature set:

cfg-rs = { version = "^0.6", features = ["full"] }

§Quick start

§1) One-liner with predefined sources

use cfg_rs::*;

let configuration = Configuration::with_predefined().unwrap();
// use configuration.get::<T>("your.key") or derive types (see below)

See PredefinedConfigurationBuilder::init for details.

§2) Customize predefined builder

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)

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, register_file, register_random, and register_prefix_env.

§4) Handy helpers for tests and small apps

  • From inline map (macro):
#[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:

#[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:


#[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 = <expr>)] on field: default value when missing

See the full reference in derive.FromConfig.

§Validation

The derive macro supports field-level validation via #[validate(...)]. The rules are implemented in src/validate.rs and are invoked after parsing field values.

Available validators:

  • range(min = <expr>, max = <expr>) for comparable values
  • length(min = <usize>, max = <usize>) 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:

#[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
  • Random values: under rand, keys like random.u8, random.string provide per-read randoms
  • Refreshing: Configuration::refresh() re-reads sources that allow refresh; RefValue<T> 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.

§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 ones1
  • This crate intentionally does not depend on serde
  • Docs.rs builds enable all features for a comprehensive reference

  1. Source precedence follows registration order — earlier registrations have higher priority. ↩ 1 2

Modules§

source
Configuration sources module, see the examples for general usage information.
validate
Validation helpers used by the #[validate(...)] field attributes.

Macros§

from_static_map
Test macro to generate config instance from a static map of key-value pairs.
impl_enum
Implement FromConfig for enums.
init_cargo_env
Collect all CARGO_PKG_* env variables, and CARGO_BIN_NAME into configuration.
inline_source
Inline config file in repo, see Supported File Formats.

Structs§

ConfigContext
Configuration Context.
Configuration
Configuration Instance, See Examples, How to Initialize Configuration for details.
FromStrHolder
Wrapper for all FromStr type.
PredefinedConfigurationBuilder
Predefined Configuration Builder. See init for details.
RefValue
RefValue means reference of value or refreshable value, it holds a value which can be updated when Configuration is refreshed.

Enums§

ConfigError
Configuration Error.
ConfigValue
Config value, ConfigSource use this value to store config properties.

Traits§

FromConfig
Generate config instance from configuration.
FromConfigWithPrefix
Config with prefix. This trait is auto derived by FromConfig.
FromStringValue
Get from string.

Functions§

from_env
Generate config instance from environment variables.
from_map
Generate config instance from a map of key-value pairs.

Type Aliases§

ConfigKey
Config key, ConfigSource use this key to access config properties.

Derive Macros§

FromConfig
Automatic derive FromConfig instance.