### Manual Layer Operations with Confique Source: https://context7.com/lukaskalbertodt/confique/llms.txt The `Layer` trait allows fine-grained control over configuration merging. This example demonstrates loading configuration from a file, creating a programmatic layer, getting default values, loading from environment variables, and merging these layers with fallback priorities. ```rust use confique::{Config, Layer, File, FileFormat}; #[derive(Debug, Config)] struct Conf { name: String, #[config(default = 100)] timeout: u32, debug: Option, } fn main() -> Result<(), confique::Error> { type ConfLayer = ::Layer; // Load from file with explicit format let from_file: ConfLayer = File::with_format("config", FileFormat::Toml) .required() .load()?; // Create layer programmatically let programmatic = ConfLayer { name: Some("Override".to_string()), timeout: None, // Don't override debug: Some(true), }; // Get default values layer let defaults = ConfLayer::default_values(); // Load from environment let from_env = ConfLayer::from_env()?; // Merge layers: earlier layers have higher priority let merged = from_env .with_fallback(programmatic) .with_fallback(from_file) .with_fallback(defaults); // Convert to final config (fails if required values missing) let config = Conf::from_layer(merged)?; println!("Final config: {:?}", config); Ok(()) } ``` -------------------------------- ### File Loading with Format Control Source: https://context7.com/lukaskalbertodt/confique/llms.txt The `File` struct allows explicit control over file loading, including format specification and required/optional handling. This example demonstrates auto-detection, explicit format, and marking files as required. ```rust use confique::{Config, File, FileFormat, Layer}; #[derive(Debug, Config)] struct Conf { name: String, #[config(default = 8080)] port: u16, } fn main() -> Result<(), confique::Error> { type ConfLayer = ::Layer; // Auto-detect format from extension (optional file) let layer1: ConfLayer = File::new("config.toml")?.load()?; // Explicit format, file without extension let layer2: ConfLayer = File::with_format("/etc/myapp/config", FileFormat::Yaml) .load()?; // Mark file as required (error if not found) let layer3: ConfLayer = File::new("required-config.toml")? .required() .load()?; // Combine layers let merged = layer1.with_fallback(layer2).with_fallback(layer3); let config = Conf::from_layer(merged.with_fallback(ConfLayer::default_values()))?; println!("{}: {}", config.name, config.port); Ok(()) } ``` -------------------------------- ### Generate TOML Configuration Templates Source: https://context7.com/lukaskalbertodt/confique/llms.txt Use `toml::template` to generate documented configuration file templates from struct definitions. This example demonstrates generating a TOML template for `AppConfig` with default options and with comments disabled for minimal output. ```rust use confique::{Config, toml::FormatOptions}; use std::path::PathBuf; /// Application configuration for MyApp. #[derive(Config)] struct AppConfig { /// The display name of the application. #[config(default = "MyApp")] app_name: String, /// Port to listen on for HTTP connections. #[config(env = "PORT", default = 8080)] port: u16, #[config(nested)] database: DbConfig, } #[derive(Config)] struct DbConfig { /// Database connection string (required). connection_url: String, /// Enable connection pooling. #[config(default = true)] pooling: bool, /// Maximum pool size. #[config(default = 20)] max_pool_size: u32, } fn main() { // Generate TOML template let toml_template = confique::toml::template::(FormatOptions::default()); println!("=== TOML Template ===\n{}", toml_template); // Generate without comments for minimal output let mut options = FormatOptions::default(); options.general.comments = false; let minimal = confique::toml::template::(options); println!("=== Minimal ===\n{}", minimal); } // Output: // === TOML Template === // # Application configuration for MyApp. // // # The display name of the application. // # // # Default value: "MyApp" // #app_name = "MyApp" // // # Port to listen on for HTTP connections. // # // # Can also be specified via environment variable `PORT`. // # // # Default value: 8080 // #port = 8080 // // [database] // # Database connection string (required). // # // # Required! This value must be specified. // #connection_url = // // # Enable connection pooling. // # // # Default value: true // #pooling = true // // # Maximum pool size. // # // # Default value: 20 // #max_pool_size = 20 ``` -------------------------------- ### Custom Deserialization with Serde Source: https://context7.com/lukaskalbertodt/confique/llms.txt Use `#[config(deserialize_with = ...)]` for custom deserialization logic, forwarding to serde's `deserialize_with` functionality. This example shows deserializing milliseconds into a `Duration` and includes validation. ```rust use confique::Config; use std::time::Duration; use serde::Deserialize; #[derive(Debug, Config)] struct Conf { /// Timeout specified as milliseconds in config, stored as Duration. #[config(deserialize_with = deserialize_duration_ms, default = 5000)] timeout: Duration, /// Request timeout with validation. #[config( deserialize_with = deserialize_duration_ms, validate(*request_timeout >= Duration::from_millis(100), "timeout must be >= 100ms") )] request_timeout: Option, } fn deserialize_duration_ms<'de, D>(deserializer: D) -> Result where D: serde::Deserializer<'de>, { let ms = u64::deserialize(deserializer)?; Ok(Duration::from_millis(ms)) } fn main() -> Result<(), confique::Error> { // Config file would contain: timeout = 3000 let config = Conf::builder() .preloaded(::Layer { timeout: Some(Duration::from_millis(3000)), request_timeout: Some(Duration::from_millis(500)), }) .load()?; println!("Timeout: {:?}", config.timeout); println!("Request timeout: {:?}", config.request_timeout); Ok(()) } ``` -------------------------------- ### Struct-Level Validation with Confique Source: https://context7.com/lukaskalbertodt/confique/llms.txt Use the `#[config(validate = ...)]` attribute on structs to validate relationships between fields after all configuration layers are merged. This example shows validation logic for replication settings. ```rust use confique::Config; #[derive(Debug, Config)] #[config(validate = Self::validate)] struct ReplicationConfig { /// Number of data replicas. #[config(default = 3)] replicas: u32, /// Minimum replicas for write acknowledgment. #[config(default = 2)] min_write_ack: u32, /// Enable synchronous replication. #[config(default = false)] sync_replication: bool, /// Sync timeout in milliseconds (only relevant if sync_replication is true). sync_timeout_ms: Option, } impl ReplicationConfig { fn validate(&self) -> Result<(), &'static str> { if self.min_write_ack > self.replicas { return Err("min_write_ack cannot exceed replicas count"); } if self.min_write_ack == 0 { return Err("min_write_ack must be at least 1"); } if self.sync_replication && self.sync_timeout_ms.is_none() { return Err("sync_timeout_ms required when sync_replication is enabled"); } Ok(()) } } fn main() -> Result<(), confique::Error> { let config = ReplicationConfig::builder() .preloaded(::Layer { replicas: Some(5), min_write_ack: Some(3), sync_replication: Some(true), sync_timeout_ms: Some(5000), }) .load()?; println!("Replicas: {}, Min Ack: {}", config.replicas, config.min_write_ack); Ok(()) } ``` -------------------------------- ### Integrate Confique with Clap CLI Parser Source: https://context7.com/lukaskalbertodt/confique/llms.txt Use `#[config(layer_attr(...))]` to derive traits for seamless integration with command-line argument parsers like clap. This example shows how to define server configuration with defaults and map them to CLI arguments. ```rust use confique::Config; use clap::Parser; use std::{net::IpAddr, path::PathBuf}; #[derive(Debug, Config)] #[config(layer_attr(derive(clap::Args)))] // Derive clap::Args for the layer struct ServerConfig { /// Server port number. #[config(default = 8080)] #[config(layer_attr(arg(short, long)))] // Configure as CLI arg port: u16, /// Bind address. #[config(default = "127.0.0.1")] #[config(layer_attr(arg(long)))] bind: IpAddr, /// Enable verbose output. #[config(default = false)] #[config(layer_attr(arg(short, long)))] verbose: bool, } #[derive(Parser)] #[command(name = "myapp", about = "Example application")] struct Cli { /// Path to configuration file. #[arg(short, long, default_value = "config.toml")] config: PathBuf, /// Server configuration (can be overridden via CLI). #[command(flatten)] server: ::Layer, } fn main() -> Result<(), confique::Error> { let cli = Cli::parse(); // CLI args > config file > defaults let config = ServerConfig::builder() .preloaded(cli.server) // CLI arguments (highest priority) .file(&cli.config) // Config file .load()?; // Defaults (lowest priority) println!("Server: {}:{}", config.bind, config.port); if config.verbose { println!("Verbose mode enabled"); } Ok(()) } // Usage: // $ myapp --port 3000 --verbose // $ myapp --config /etc/myapp.toml -p 8000 ``` -------------------------------- ### Load Configuration with Builder API Source: https://context7.com/lukaskalbertodt/confique/llms.txt Use the fluent builder API to chain multiple configuration sources where earlier sources take precedence. ```rust use confique::Config; #[derive(Debug, Config)] struct Conf { #[config(env = "APP_PORT", default = 3000)] port: u16, #[config(env = "APP_HOST", default = "localhost")] host: String, #[config(default = false)] debug: bool, } fn main() -> Result<(), confique::Error> { // Sources are checked in order; first source wins for each value let config = Conf::builder() .env() // Highest priority: environment variables .file("./config.local.toml") // Optional local overrides .file("./config.toml") // Main config file .file("/etc/myapp/config.toml") // System-wide defaults .load()?; // Lowest: #[config(default = ...)] values // All required values must be found somewhere in the chain println!("Running on {}:{}", config.host, config.port); Ok(()) } ``` -------------------------------- ### Load Configuration from Single File Source: https://context7.com/lukaskalbertodt/confique/llms.txt Use from_file to load configuration from a single file with automatic format detection based on the file extension. ```rust use confique::Config; #[derive(Debug, Config)] struct ServerConfig { host: String, port: u16, #[config(default = 30)] timeout_seconds: u32, } fn main() -> Result<(), confique::Error> { // Format detected from extension: .toml, .yaml, .yml, .json5, .json let config = ServerConfig::from_file("server.toml")?; println!("Server: {}:{}", config.host, config.port); println!("Timeout: {}s", config.timeout_seconds); Ok(()) } // Example server.toml contents: // host = "0.0.0.0" // port = 8080 ``` -------------------------------- ### Load Environment Variables with Confique Source: https://context7.com/lukaskalbertodt/confique/llms.txt Demonstrates loading configuration from environment variables using `Layer::from_env()` or the builder's `.env()` method. Supports default values and various boolean representations. ```rust use confique::Config; #[derive(Debug, Config)] struct Conf { /// Loaded from DATABASE_URL environment variable. #[config(env = "DATABASE_URL")] database_url: String, /// Port from PORT env var, defaults to 8080. #[config(env = "PORT", default = 8080)] port: u16, /// Boolean values accept: true/false, yes/no, 1/0 (case-insensitive). #[config(env = "DEBUG", default = false)] debug: bool, } fn main() -> Result<(), confique::Error> { // Set environment variables std::env::set_var("DATABASE_URL", "postgres://localhost/mydb"); std::env::set_var("PORT", "3000"); std::env::set_var("DEBUG", "yes"); let config = Conf::builder().env().load()?; assert_eq!(config.database_url, "postgres://localhost/mydb"); assert_eq!(config.port, 3000); assert_eq!(config.debug, true); Ok(()) } ``` -------------------------------- ### Define and Load Configuration Source: https://github.com/lukaskalbertodt/confique/blob/main/README.md Use the Config derive macro to define configuration structures with default values, environment variable mappings, and validation. The builder pattern allows chaining multiple configuration sources. ```rust use std::{net::IpAddr, path::PathBuf}; use confique::Config; #[derive(Config)] struct Conf { /// Port to listen on. #[config(env = "PORT", default = 8080)] port: u16, /// Bind address. #[config(default = "127.0.0.1")] address: IpAddr, #[config(nested)] log: LogConf, } #[derive(Config)] struct LogConf { #[config(default = true)] stdout: bool, #[config(validate(file.is_absolute(), "log file requires absolute path"))] file: Option, #[config(default = ["debug"])] ignored_modules: Vec, } let config = Conf::builder() .env() .file("example-app.toml") .file("/etc/example-app/config.toml") .load()?; ``` -------------------------------- ### Generate Configuration Templates Source: https://github.com/lukaskalbertodt/confique/blob/main/README.md Automatically generate configuration templates in TOML, YAML, or JSON5 formats based on the defined configuration struct. ```toml # Port to listen on. # # Can also be specified via # environment variable `PORT`. # # Default value: 8080 #port = 8080 # Bind address. # # Default value: "127.0.0.1" #address = "127.0.0.1" [log] # ``` ```yaml # Port to listen on. # # Can also be specified via # environment variable `PORT`. # # Default value: 8080 #port: 8080 # Bind address. # # Default value: 127.0.0.1 #address: 127.0.0.1 log: # ``` ```json5 { // Port to listen on. // // Can also be specified via // environment variable `PORT`. // // Default value: 8080 //port: 8080, // Bind address. // // Default value: "127.0.0.1" //address: "127.0.0.1", log: { // }, } ``` -------------------------------- ### Define Configuration Schema with Derive Config Source: https://context7.com/lukaskalbertodt/confique/llms.txt Use the #[derive(Config)] macro to define nested configuration structures with default values and environment variable mappings. ```rust use confique::Config; use std::{net::IpAddr, path::PathBuf}; /// Main application configuration. #[derive(Debug, Config)] struct AppConfig { /// Port the server listens on. #[config(env = "PORT", default = 8080)] port: u16, /// Server bind address. #[config(default = "127.0.0.1")] bind: IpAddr, /// Optional welcome message displayed to users. welcome_message: Option, #[config(nested)] database: DatabaseConfig, #[config(nested)] logging: LogConfig, } #[derive(Debug, Config)] struct DatabaseConfig { /// Database connection URL (required). connection_url: String, /// Maximum connection pool size. #[config(default = 10)] max_connections: u32, } #[derive(Debug, Config)] struct LogConfig { /// Enable stdout logging. #[config(default = true)] stdout: bool, /// Optional log file path. log_file: Option, /// Modules to ignore in logging. #[config(default = ["hyper", "tower"])] ignored_modules: Vec, } fn main() -> Result<(), confique::Error> { let config = AppConfig::builder() .env() .file("config.toml") .file("/etc/myapp/config.toml") .load()?; println!("Server running on {}:{}", config.bind, config.port); println!("Database: {}", config.database.connection_url); Ok(()) } ``` -------------------------------- ### Field Validation with Confique Source: https://context7.com/lukaskalbertodt/confique/llms.txt Shows how to use `#[config(validate = ...)]` for custom function-based validation and inline assert-style expressions. Supports validation on optional fields, which are only checked when a value is present. ```rust use confique::Config; use std::path::PathBuf; #[derive(Debug, Config)] struct Conf { /// Validate using a function that returns Result<(), impl Display>. #[config(validate = validate_username)] username: String, /// Assert-style inline validation with error message. #[config(validate(*port >= 1024, "ports below 1024 require root privileges"))] port: u16, /// Multiple validations on a single field. #[config( validate(!name.is_empty(), "name cannot be empty"), validate(name.len() <= 64, "name too long (max 64 chars)"), validate(name.is_ascii(), "name must contain only ASCII characters") )] name: String, /// Validation on optional fields checks only when value is present. #[config(validate(path.is_absolute(), "log path must be absolute"))] log_path: Option, } fn validate_username(username: &String) -> Result<(), &'static str> { if username.is_empty() { return Err("username cannot be empty"); } if username == "root" || username == "admin" { return Err("reserved username not allowed"); } if !username.chars().all(|c| c.is_alphanumeric() || c == '_') { return Err("username must be alphanumeric with underscores only"); } Ok(()) } fn main() { std::env::set_var("USERNAME", "alice_123"); std::env::set_var("PORT", "8080"); std::env::set_var("NAME", "MyApp"); // This will succeed let result = Conf::builder().env().load(); assert!(result.is_ok()); // This will fail validation std::env::set_var("PORT", "80"); let result = Conf::builder().env().load(); assert!(result.is_err()); } ``` -------------------------------- ### Custom Environment Variable Parsing in Confique Source: https://context7.com/lukaskalbertodt/confique/llms.txt Illustrates using `#[config(parse_env = ...)]` for custom parsing of complex types from environment variables, including lists separated by colons, commas, or custom delimiters, and fully custom parser functions. ```rust use confique::Config; use std::{collections::HashSet, path::PathBuf}; #[derive(Debug, Config)] struct Conf { /// Parse colon-separated paths (like $PATH). #[config(env = "SEARCH_PATHS", parse_env = confique::env::parse::list_by_colon)] search_paths: HashSet, /// Parse comma-separated port list. #[config(env = "ALLOWED_PORTS", parse_env = confique::env::parse::list_by_comma)] allowed_ports: Vec, /// Custom separator using generic function. #[config(env = "TAGS", parse_env = confique::env::parse::list_by_sep::<'|', _, _>)] tags: Vec, /// Fully custom parser function. #[config(env = "FEATURES", parse_env = parse_features)] features: Vec, } #[derive(Debug, Clone)] enum Feature { Alpha, Beta, Stable } fn parse_features(input: &str) -> Result, std::convert::Infallible> { let mut features = Vec::new(); if input.contains("alpha") { features.push(Feature::Alpha); } if input.contains("beta") { features.push(Feature::Beta); } if input.contains("stable") { features.push(Feature::Stable); } Ok(features) } fn main() -> Result<(), confique::Error> { std::env::set_var("SEARCH_PATHS", "/usr/bin:/usr/local/bin:/home/user/bin"); std::env::set_var("ALLOWED_PORTS", "80,443,8080"); std::env::set_var("TAGS", "web|api|internal"); std::env::set_var("FEATURES", "alpha,beta"); let config = Conf::builder().env().load()?; assert_eq!(config.search_paths.len(), 3); assert_eq!(config.allowed_ports, vec![80, 443, 8080]); assert_eq!(config.tags, vec!["web", "api", "internal"]); Ok(()) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.