derive-defs 0.0.8

Library for generating derive preset macros from TOML configuration
Documentation
//! Complete example showing all derive-defs features.
//!
//! This example demonstrates:
//! - Basic definitions
//! - Inheritance with `extends`
//! - Attributes (`attrs`)
//! - Cross-file includes (simulated)
//! - Code generation
//!
//! # Running the example
//!
//! ```bash
//! cargo run --example complete
//! ```

use std::fs;

fn main() {
    println!("Complete Derive-Defs Example");
    println!("=============================");
    println!();

    let temp_dir = std::env::temp_dir().join("derive_defs_complete_example");
    let _ = fs::create_dir_all(&temp_dir);

    // Create shared/common_defs.toml (simulating cross-file includes)
    let common_config = r#"
[defs.serialization]
traits = ["Clone", "Serialize", "Deserialize"]
attrs = ['#[serde(rename_all = "camelCase")]']

[defs.json]
traits = ["Clone", "Serialize", "Deserialize"]
attrs = ['#[serde(rename_all = "camelCase")]']
"#;

    let common_path = temp_dir.join("common_defs.toml");
    fs::write(&common_path, common_config).expect("Failed to write common config");

    // Create main derive_defs.toml with includes
    let main_config = format!(
        r#"
[includes]
common = "{}"

# Base definitions
[defs.debug]
traits = ["Debug"]

[defs.model]
extends = "debug"
traits = ["Clone", "PartialEq"]

[defs.entity]
extends = "common.serialization"
traits = ["Default"]

[defs.value_object]
extends = "model"
traits = ["Eq", "Hash", "Copy"]

[defs.event]
extends = "common.serialization"
traits = ["Debug", "Hash", "Eq"]

[defs.config]
traits = ["Debug", "Clone", "Default", "Serialize", "Deserialize"]
attrs = [
    '#[serde(default)]',
    '#[serde(deny_unknown_fields)]',
]
"#,
        common_path.display()
    );

    let main_path = temp_dir.join("derive_defs.toml");
    fs::write(&main_path, &main_config).expect("Failed to write main config");

    println!("Common definitions (common_defs.toml):");
    println!("{common_config}");
    println!();

    println!("Main configuration (derive_defs.toml):");
    println!("{main_config}");
    println!();

    // Parse the configuration
    let parsed = derive_defs::parser::parse_file(&main_path).expect("Failed to parse");
    println!("Parsed {} definitions from main file", parsed.defs.len());
    println!("Includes: {:?}", parsed.includes.keys().collect::<Vec<_>>());
    println!();

    // Resolve includes (if we were doing full include resolution)
    // For this example, we'll skip actual include resolution and just resolve
    // the main definitions
    let resolved = derive_defs::resolver::resolve(&parsed).expect("Failed to resolve");

    println!("Resolved definitions:");
    println!();

    // Group definitions by category
    let mut categories: std::collections::HashMap<&str, Vec<&str>> =
        std::collections::HashMap::new();
    categories.insert("Base", vec!["debug", "model"]);
    categories.insert("Domain", vec!["entity", "value_object", "event"]);
    categories.insert("Config", vec!["config"]);

    for (category, names) in categories {
        println!("{category}:");
        for name in names {
            if let Some(def) = resolved.defs.get(name) {
                println!("  [defs.{name}]");
                println!("    traits: {:?}", def.traits);
                if !def.attrs.is_empty() {
                    println!("    attrs: {:?}", def.attrs);
                }
            }
        }
        println!();
    }

    // Generate code
    let output_path = temp_dir.join("generated.rs");
    derive_defs::generate_from_resolved(resolved, &output_path).expect("Failed to generate");

    println!("Generated code preview (first 1000 chars):");
    let generated = fs::read_to_string(&output_path).expect("Failed to read output");
    let preview: String = generated.chars().take(1000).collect();
    println!("{preview}");
    if generated.len() > 1000 {
        println!("\n... ({} more characters)", generated.len() - 1000);
    }

    // Cleanup
    let _ = fs::remove_dir_all(&temp_dir);

    println!();
    println!("Example completed successfully!");
    println!();
    println!("Summary:");
    println!("  - Parsed TOML configuration");
    println!("  - Resolved inheritance chains");
    println!("  - Generated proc-macro code");
    println!();
    println!("Next steps:");
    println!("  1. Use the generated code in a proc-macro crate");
    println!("  2. Import and use the generated macros");
    println!("  3. Apply #[serialization], #[model], etc. to your types");
}