cfgmatic-files 2.2.0

Configuration file discovery and reading with multiple format support
Documentation

cfgmatic-files

License Unsafe rustc

Configuration file discovery and reading with multiple format support.

Overview

cfgmatic-files provides a simple, cross-platform way to discover and parse configuration files following platform conventions (via cfgmatic-paths). It supports multiple serialization formats and handles configuration merging with proper priority handling.

Features

  • Multiple Formats: TOML, JSON, YAML (see note below)
  • Cross-platform: Uses cfgmatic-paths for platform-specific directories
  • Priority-based Merging: User > Local > System
  • Type-safe Parsing: Deserialize directly into your structs
  • Flexible Discovery: Find all files or just the first available

YAML Support Notice

LEGACY: The yaml feature is considered legacy. The serde_yaml crate is deprecated by its author and may be removed in future versions. See: https://github.com/dtolnay/serde-yaml/issues/344

Installation

[dependencies]
cfgmatic-files = "0.1"

Enable features as needed:

[dependencies]
cfgmatic-files = { version = "0.1", features = ["toml", "json"] }

Quick Start

Finding Configuration Files

use cfgmatic_files::FileFinder;

// Find all config files for an application
let files = FileFinder::new("myapp").find()?;

for file in &files {
    println!("Found: {} ({:?})", file.path.display(), file.tier);
}

Parsing Configurations

use cfgmatic_files::FileFinder;
use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct Config {
    timeout: u32,
    host: String,
}

let files = FileFinder::new("myapp").find()?;

if let Some(file) = files.first() {
    let config: Config = file.parse()?;
    println!("Timeout: {}, Host: {}", config.timeout, config.host);
}

Loading and Merging

use cfgmatic_files::load_merged;
use serde::Deserialize;

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

// Load and merge all config files (User > Local > System)
let config: Config = load_merged("myapp")?;

Finding First Available

use cfgmatic_files::{load_first, FileFinder};

// Load the first available config file
let config: Option<Config> = load_first("myapp")?;

// Or find the file first
let files = FileFinder::new("myapp").find()?;
if let Some(file) = files.first() {
    // Use file.path() to access the path
    println!("Config file: {}", file.path().display());
}

Configuration Priority

Files are searched and prioritized by tier (highest to lowest):

  1. User (ConfigTier::User): User-specific configs

    • Unix/Linux: ~/.config/myapp/
    • macOS: ~/Library/Application Support/myapp/ (GUI apps)
    • Windows: %APPDATA%\myapp\
  2. Local (ConfigTier::Local): Machine-specific configs

    • Unix/Linux: /usr/local/etc/myapp/, /etc/myapp/
    • macOS: /Library/Application Support/myapp/
    • Windows: %PROGRAMDATA%\myapp\
  3. System (ConfigTier::System): System-wide configs

    • Unix/Linux: /etc/myapp/, /etc/xdg/myapp/
    • Windows: %PROGRAMDATA%\myapp\

When merging configurations, higher tiers override values from lower tiers.

Supported Formats

TOML (default)

# config.toml
timeout = 30
host = "localhost"
let files = FileFinder::new("myapp")
    .formats(&[Format::Toml])
    .find()?;

JSON (default)

{
  "timeout": 30,
  "host": "localhost"
}
let files = FileFinder::new("myapp")
    .formats(&[Format::Json])
    .find()?;

YAML (legacy feature)

timeout: 30
host: localhost
let files = FileFinder::new("myapp")
    .formats(&[Format::Yaml])
    .find()?;

Advanced Usage

Custom Format Selection

use cfgmatic_files::{FileFinder, Format};

// Search for TOML and JSON, preferring TOML
let files = FileFinder::new("myapp")
    .formats(&[Format::Toml, Format::Json])
    .find()?;

Tier-specific Searching

use cfgmatic_files::{FileFinder, ConfigTier};

// Only search user directories
let files = FileFinder::new("myapp")
    .tiers(&[ConfigTier::User])
    .find()?;

Merging Custom Types

use cfgmatic_files::{ConfigFiles, Mergeable};
use serde::Deserialize;

#[derive(Debug, Deserialize, Default)]
struct Config {
    port: u16,
    #[serde(default)]
    database: DatabaseConfig,
}

#[derive(Debug, Deserialize, Default)]
struct DatabaseConfig {
    url: String,
    pool_size: u32,
}

let files = FileFinder::new("myapp").find()?;
let config: Config = files.merge()?;

Examples

# Find and display all config files
cargo run --example find_files

# Load and parse TOML config
cargo run --example load_toml

# Merge multiple config files
cargo run --example merge_configs

Feature Flags

  • default: Enables toml and json features
  • toml: TOML format support (via toml crate)
  • json: JSON format support (via serde_json)
  • yaml: YAML format support (via serde_yaml, legacy)
  • async: Async support via tokio

Relationship to cfgmatic

This crate is part of the cfgmatic configuration framework:

  • cfgmatic-paths: Platform-specific path discovery
  • cfgmatic-files: File discovery and parsing (this crate)
  • cfgmatic: High-level API with environment variables and validation

License

This project is licensed under either of:

at your option.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for details.