#builder #ini #macro #serde

config-tools

A simplified set of tools for working with configuration files

8 unstable releases (3 breaking)

new 0.5.0 May 5, 2025
0.4.0 Mar 20, 2025
0.3.4 Mar 14, 2025
0.3.2 Nov 12, 2024
0.1.0 Oct 15, 2024

#332 in Configuration

Download history 7/week @ 2025-01-15 3/week @ 2025-01-29 15/week @ 2025-02-05 5/week @ 2025-02-12 5/week @ 2025-02-26 249/week @ 2025-03-12 146/week @ 2025-03-19 5/week @ 2025-03-26 2/week @ 2025-04-09 101/week @ 2025-04-30

103 downloads per month

MIT/Apache

17KB
238 lines

config_tools

config_tools is a lightweight, ergonomic Rust library for working with INI-style configuration files. It offers:

  • A builder pattern for programmatic config creation
  • Macros for concise default declarations
  • Optional typed section parsing using FromSection
  • Graceful fallbacks with load_or_default_outcome
  • serde support for full serialization and deserialization

It is built on top of rust-ini and designed for developer ergonomics first.


Quickstart

use config_tools::{Config, sectioned_defaults};

let outcome = Config::load_or_default_outcome(
    "config.ini",
    sectioned_defaults! {
        { "debug" => "true" }
        
        ["App"] {
            "threads" => "4"
        }
    }
);

if outcome.used_default() {
    eprintln!("Using fallback config.");
}

let config = outcome.into_inner();

Manual Configuration

use config_tools::Config;

let config = Config::builder()
    .general()
    .set("logging", "true")
    .set("verbose", "false")
    .section("Database")
    .set("host", "localhost")
    .set("port", "5432")
    .build();

Macros for Inline Defaults

use config_tools::{sectioned_defaults, general_defaults, Config};

let sectioned: Config = sectioned_defaults! {
    { "logging" => "true" }

    ["Server"] {
        "host" => "127.0.0.1",
        "port" => "8080"
    }
};

let general: Config = general_defaults! {
    "console" => "true",
    "logging" => "true",
};

Loading and Saving Configs

use config_tools::Config;

let config = Config::load("config.ini")?;
config.save("out.ini")?;

You can also handle missing files gracefully:

let default = Config::builder().set("fallback", "true").build();
let config = Config::load_or_default("config.ini", default);

Or check whether defaults were used:

let outcome = Config::load_or_default_outcome("config.ini", Config::default());

if outcome.used_default() {
    println!("File not found; using defaults.");
}

let config = outcome.into_inner();

Typed Section Parsing with FromSection

use config_tools::{Config, FromSection};

#[derive(FromSection)]
struct ServerConfig {
    host: String,
    port: u16,
}

let config = Config::load("config.ini")?;
let server_section = config.section("Server").unwrap();
let server: ServerConfig = ServerConfig::from_section(server_section)?;

Config API

  • Config::builder(): Starts a new builder
  • Config::load(path): Loads from file
  • Config::save(path): Saves to file
  • Config::load_or_default(path, default): Uses a fallback if loading fails
  • Config::load_or_default_outcome(...): Same as above, but returns LoadOutcome
  • config.get(section, key): Returns a value as Option<String>
  • config.get_as::<T>(...): Parses value into a type
  • config.update(...): Updates or inserts a key-value pair

LoadOutcome

Returned from load_or_default_outcome:

  • LoadOutcome::FromFile(config)
  • LoadOutcome::FromDefault(config)

Methods:

  • .into_inner(): Extract the config
  • .as_ref(), .as_mut(): Borrow access
  • .used_default() -> bool: Did fallback occur?

Macros

sectioned_defaults!

let config = sectioned_defaults! {
    { "logging" => "true" }

    ["App"] {
        "theme" => "dark"
    }
};

Supports variables for section names, keys, and values (must be strings). General keys must come first.


general_defaults!

let config = general_defaults! {
    "logging" => "true",
    "console" => "true"
};

Procedural Macro: #[derive(FromSection)]

Allows typed parsing of section contents:

#[derive(FromSection)]
struct MySettings {
    path: String,
    enabled: bool,
}

Fields must implement FromStr.

Dependencies

~1.5–2.3MB
~43K SLoC