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);
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");
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!();
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!();
let resolved = derive_defs::resolver::resolve(&parsed).expect("Failed to resolve");
println!("Resolved definitions:");
println!();
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!();
}
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);
}
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");
}