Skip to main content

Crate gifnoc

Crate gifnoc 

Source
Expand description

Type-safe configuration with layered overrides.

gifnoc provides a config! macro that generates a configuration struct with typed fields and compile-time defaults. The struct implements the Configurable trait, whose update method applies overrides from any source — environment variables, CLI flags, TOML or YAML files — without clobbering unrelated fields.

§Quick start

use gifnoc::{config, Configurable};

config! {
    ServerConfig {
        host: String = "localhost",
        port: u32 = 8080u32,
    }
}

let config = ServerConfig::default();
assert_eq!(config.host, "localhost");
assert_eq!(config.port, 8080);

§Sources

All source functions return serde_json::Value and plug into Configurable::update via the same flatten → merge → nest pipeline. Sources are layered by chaining .update() calls — later calls win:

let (actions, flags) = gifnoc::args::parse();
let config = AppConfig::default()
    .update(gifnoc::env::with_prefix("APP"))   // env vars override defaults
    .update(flags);                             // CLI flags override env vars
SourceFunctionConvention
Environment variablesenv::with_prefixAPP_KEY, APP_SECTION__KEY
CLI flagsargs::parse--key value, --section.key value
JSON filejson::from_fileround-trips Configurable::to_json output
TOML file[toml::from_file](requires feature toml)
YAML file[yaml::from_file](requires feature yaml)

Build the full config once in main, then distribute slices to subsystems via their constructors. Each subsystem receives only the section it needs, keeping dependencies narrow:

use gifnoc::{config, Configurable};

config! { ServerConfig { port: u32 = 8080u32 } }
config! { AppConfig { server: ServerConfig = ServerConfig::default() } }

struct Server { port: u32 }

impl Server {
    fn new(config: &ServerConfig) -> Self {
        Server { port: config.port }
    }
    fn run(&self) { println!("listening on :{}", self.port); }
}

fn main() {
    let (actions, flags) = gifnoc::args::parse();
    let config = AppConfig::default()
        .update(gifnoc::env::with_prefix("APP"))
        .update(flags);

    let server = Server::new(&config.server);

    for action in &actions {
        match action.as_str() {
            "serve" => server.run(),
            other => { eprintln!("unknown action: {other}"); std::process::exit(1); }
        }
    }
}

Modules§

args
env
json

Macros§

config
Defines a configuration struct with typed fields and compile-time defaults.

Traits§

Configurable
Trait for configuration structs that support layered overrides.