confyg

Crates.ioconfyg
lib.rsconfyg
version0.3.0
created_at2022-11-13 19:05:13.364934+00
updated_at2026-01-14 17:59:18.948309+00
descriptionA simple, TOML-based, ENV-enabled library that can find and merge configs
homepage
repositoryhttps://github.com/oxur/confyg
max_upload_size
id714443
size163,657
Duncan McGreggor (oubiwann)

documentation

https://docs.rs/confyg/

README

confyg

A simple, TOML-based, ENV-enabled library for configuration management

Overview

confyg provides a flexible way to build application configurations by:

  • Loading from TOML files with path searching
  • Scanning environment variables with prefix mapping
  • Merging multiple configuration sources with override semantics
  • Deserializing directly into strongly-typed Rust structs

Features

  • Multiple Sources: Combine TOML files, environment variables, strings, and Rust structs
  • Path Search: Automatically search multiple directories for configuration files
  • Environment Variable Mapping: Map prefixed environment variables to TOML sections
  • Deep Merging: Intelligently merge configurations with clear priority rules
  • Type Safety: Deserialize directly into your Rust types using serde
  • Error Handling: Comprehensive error types with context preservation
  • Zero Unsafe: Pure safe Rust with no unsafe code

Quick Start

Add to your Cargo.toml:

[dependencies]
confyg = "0.3"
serde = { version = "1.0", features = ["derive"] }

Basic example:

use confyg::{Confygery, Result};
use serde_derive::Deserialize;

#[derive(Debug, Deserialize)]
struct Config {
    env: String,
    database: Database,
}

#[derive(Debug, Deserialize)]
struct Database {
    host: String,
    port: u16,
}

fn main() -> Result<()> {
    let config: Config = Confygery::new()?
        .add_file("defaults.toml")?
        .add_file("production.toml")?
        .build()?;

    println!("Environment: {}", config.env);
    println!("Database: {}:{}", config.database.host, config.database.port);
    Ok(())
}

Usage Examples

Loading from Files

use confyg::{Confygery, conf, Result};

let mut opts = conf::Options::default();
opts.add_path("./config")
    .add_path("/etc/myapp")
    .add_path("/usr/local/etc/myapp");

let config: MyConfig = Confygery::new()?
    .with_opts(opts)?
    .add_file("defaults.toml")?
    .add_file("production.toml")?
    .build()?;

Environment Variables

Environment variables follow the pattern: TOPLEVEL_SECTION_KEY=value

# Set environment variables
export MYAPP_ENV=production
export MYAPP_DATABASE_HOST=db.example.com
export MYAPP_DATABASE_PORT=5432
use confyg::{Confygery, env, Result};

let mut env_opts = env::Options::with_top_level("myapp");
env_opts.add_section("database");

let config: MyConfig = Confygery::new()?
    .add_file("defaults.toml")?
    .add_env(env_opts)?  // Environment overrides file config
    .build()?;

Configuration Priority

Sources added later override earlier sources:

Confygery::new()?
    .add_str(defaults_toml)?       // Priority: 1 (lowest)
    .add_file("defaults.toml")?    // Priority: 2
    .add_file("production.toml")?  // Priority: 3
    .add_env(env_opts)?            // Priority: 4 (highest)
    .build()?

Inline Configuration

let config: MyConfig = Confygery::new()?
    .add_str(r#"
        env = "development"

        [database]
        host = "localhost"
        port = 5432
    "#)?
    .build()?;

From Rust Structs

use serde_derive::Serialize;

#[derive(Serialize)]
struct Defaults {
    timeout: u32,
    retries: u8,
}

let defaults = Defaults {
    timeout: 30,
    retries: 3,
};

let config: MyConfig = Confygery::new()?
    .add_struct(&defaults)?
    .add_file("config.toml")?
    .build()?;

Environment Variable Naming

Environment variables are converted to lowercase TOML keys:

Environment Variable TOML Equivalent
MYAPP_ENV env = "..."
MYAPP_LOG_LEVEL log_level = "..."
MYAPP_DATABASE_HOST [database]
host = "..."
MYAPP_DATABASE_PORT [database]
port = "..."

Note: Due to environment variable naming limitations:

  • Use underscores instead of dots in section names
  • Hyphens in section names become underscores (e.g., my-appMY_APP)
  • All keys are converted to lowercase

Examples

See the examples directory for complete working examples:

Run examples:

make demos   # Run all examples with environment variables set

API Documentation

Full API documentation is available on docs.rs.

Error Handling

All operations return Result<T, ConfigError> with descriptive error messages:

match Confygery::new()?.add_file("config.toml")?.build::<MyConfig>() {
    Ok(config) => println!("Loaded config: {:?}", config),
    Err(e) => eprintln!("Configuration error: {}", e),
}

Error types include:

  • FileRead - Failed to read a file
  • TomlParse - Invalid TOML syntax
  • TomlSerialize - Failed to serialize to TOML
  • FileNotFound - File not found in search paths
  • NoConfigs - No configuration sources added
  • InvalidState - Invalid configuration state
  • InvalidPath - Path contains invalid UTF-8

Requirements

  • Rust 1.75 or later
  • serde with derive feature for deserialization

License

Copyright © 2022-2026, Oxur Group

Apache License, Version 2.0

Commit count: 48

cargo fmt