cfgmatic 1.1.0

High-level configuration management framework for Rust with derive macros and validation
Documentation
//! Test for cfgmatic with complex types (`HashMap`, nested structs)
//!
//! This test verifies that cfgmatic works correctly with structs containing
//! complex types that don't implement `FromStr`.

use cfgmatic::Config;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// Complex config with `HashMap` and nested structs
#[derive(Debug, Clone, Deserialize, Serialize, Config)]
#[config(prefix = "TEST")]
pub struct ComplexConfig {
    /// Simple field with config attribute
    #[config(default = "8080")]
    pub port: u16,

    /// Complex field WITHOUT config attribute - should be skipped
    pub registry: HashMap<String, ModelDefinition>,

    /// Nested struct WITHOUT config attribute - should be skipped
    pub nested: NestedConfig,
}

impl Default for ComplexConfig {
    fn default() -> Self {
        let mut registry = HashMap::new();
        registry.insert(
            "default".to_string(),
            ModelDefinition {
                name: "default-model".to_string(),
                dimensions: 1536,
            },
        );

        Self {
            port: 8080,
            registry,
            nested: NestedConfig::default(),
        }
    }
}

/// Model definition (stored in `HashMap`)
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ModelDefinition {
    pub name: String,
    pub dimensions: usize,
}

/// Nested configuration struct
#[derive(Debug, Clone, Deserialize, Serialize, Config)]
pub struct NestedConfig {
    /// Field with config attribute in nested struct
    #[config(default = "true")]
    pub enabled: bool,

    /// Field without config attribute
    pub value: Option<String>,
}

impl Default for NestedConfig {
    fn default() -> Self {
        Self {
            enabled: true,
            value: None,
        }
    }
}

fn main() {
    println!("Testing cfgmatic with complex types...\n");

    // Test: Default config
    let config = ComplexConfig::default();
    println!("Default config:");
    println!("  port: {}", config.port);
    println!(
        "  registry keys: {:?}",
        config.registry.keys().collect::<Vec<_>>()
    );
    println!("  nested.enabled: {}", config.nested.enabled);
    println!();

    // Verify default values
    assert_eq!(config.port, 8080, "Port should have default value");
    assert!(
        config.registry.contains_key("default"),
        "Registry should have default value"
    );
    assert!(
        config.nested.enabled,
        "Nested enabled should have default value"
    );

    println!("All checks passed!");
    println!();
    println!("The Config derive macro correctly:");
    println!("- Processes fields with #[config(...)] attributes");
    println!("- Skips complex fields (HashMap) without #[config(...)]");
    println!("- Skips nested structs without #[config(...)]");
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_complex_config_default() {
        let config = ComplexConfig::default();
        assert_eq!(config.port, 8080);
        assert!(config.registry.contains_key("default"));
        assert!(config.nested.enabled);
    }

    #[test]
    fn test_hashmap_field_preserved() {
        // This test verifies that HashMap fields are skipped by the macro
        // If they weren't, the struct wouldn't compile
        let config = ComplexConfig::default();

        // HashMap should retain its default value
        assert!(config.registry.contains_key("default"));
        assert_eq!(config.registry["default"].dimensions, 1536);
    }
}