zonfig loads JSON, YAML, and TOML config files into Serde types, then keeps a watched config handle up to date while the process is running.
- JSON, YAML, and TOML support.
- Extension-based format detection, with an explicit format override when needed.
- A cloneable
Config<T>handle that works well in HTTP application state. - Hot reload hooks for successful updates and reload errors.
- A cooldown window to avoid repeated reloads during save bursts.
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct AppConfig {
host: String,
port: u16,
}
fn main() -> Result<(), zonfig::Error> {
let config: AppConfig = zonfig::load("config.toml")?;
println!("{}:{}", config.host, config.port);
Ok(())
}use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct AppConfig {
host: String,
port: u16,
}
#[tokio::main]
async fn main() -> Result<(), zonfig::Error> {
let config = zonfig::watch::<AppConfig>("config.toml").await?;
config.with(|current| {
println!("current config: {}:{}", current.host, current.port);
});
config.on_change(|config| {
println!("config changed: {}:{}", config.host, config.port);
});
config.on_error(|error| {
eprintln!("config reload failed: {error}");
});
Ok(())
}Config<T> is cheap to clone. Store it in application state and call with or get whenever a handler needs the current value.
For example:
#[derive(Clone)]
struct AppState {
config: zonfig::Config<AppConfig>,
}Set a reload cooldown:
let config = zonfig::watch_with_options::<AppConfig>(
"config.toml",
zonfig::WatchOptions::default()
.with_cooldown(std::time::Duration::from_millis(500)),
)
.await?;- Reads use
ArcSwap, sogetreturns anArc<T>snapshot without cloning the config. - A failed reload keeps the last valid config.
- The watcher stays alive until all
Config<T>handles are dropped. - This crate intentionally focuses on local files. It does not merge multiple files, read remote config stores, or write config files back to disk.