use cfgmatic_source::prelude::*;
use serde::Deserialize;
use std::io::Write;
#[derive(Debug, Deserialize)]
struct AppConfig {
name: String,
version: String,
#[serde(default)]
debug: bool,
}
fn main() -> Result<()> {
println!("=== cfgmatic-source File Example ===\n");
toml_file_example()?;
json_file_example()?;
multiple_files_example()?;
optional_file_example()?;
println!("\nAll examples completed successfully!");
Ok(())
}
fn toml_file_example() -> Result<()> {
println!("--- TOML File Example ---");
let mut temp_file = tempfile::NamedTempFile::with_suffix(".toml").unwrap();
writeln!(
temp_file,
r#"
name = "my-app"
version = "1.0.0"
debug = true
"#
)
.unwrap();
let source = FileSource::new(temp_file.path());
let loader = Loader::new();
let config: AppConfig = loader.load_as(&source)?;
println!(
"Loaded from TOML: name={}, version={}, debug={}",
config.name, config.version, config.debug
);
Ok(())
}
fn json_file_example() -> Result<()> {
println!("\n--- JSON File Example ---");
let mut temp_file = tempfile::NamedTempFile::with_suffix(".json").unwrap();
writeln!(
temp_file,
r#"{{
"name": "json-app",
"version": "2.0.0",
"debug": false
}}"#
)
.unwrap();
let source = FileSource::new(temp_file.path());
let loader = Loader::new();
let config: AppConfig = loader.load_as(&source)?;
println!(
"Loaded from JSON: name={}, version={}, debug={}",
config.name, config.version, config.debug
);
Ok(())
}
fn multiple_files_example() -> Result<()> {
println!("\n--- Multiple Files Example ---");
let mut base_file = tempfile::NamedTempFile::with_suffix(".toml").unwrap();
writeln!(
base_file,
r#"
name = "base-app"
version = "1.0.0"
debug = false
"#
)
.unwrap();
let mut local_file = tempfile::NamedTempFile::with_suffix(".toml").unwrap();
writeln!(
local_file,
r"
debug = true
"
)
.unwrap();
let source = FileSource::builder()
.path(base_file.path())
.path(local_file.path())
.build()?;
let loader = Loader::new();
let config: AppConfig = loader.load_as(&source)?;
println!(
"Merged config: name={}, version={}, debug={}",
config.name, config.version, config.debug
);
println!(" Note: debug=true came from local file");
Ok(())
}
fn optional_file_example() -> Result<()> {
println!("\n--- Optional File Example ---");
let source = FileSource::builder()
.path("/nonexistent/config.toml")
.required(false)
.build()?;
match source.load_raw() {
Ok(content) if content.is_empty() => {
println!("Optional file not found, using empty content");
}
Ok(content) => {
println!("Loaded {} bytes", content.len());
}
Err(e) => {
println!("Error loading optional file: {e}");
}
}
println!(" Tip: Use required(false) for user-specific configs");
Ok(())
}