vulkan_gen 0.3.0

Vulkan XML specification parser and Rust binding generator. Used internally by the vulkane crate, but reusable as a standalone code generator.
Documentation
//! Includes generator module
//!
//! Generates Rust include handling code from includes.json intermediate file

use std::fs;
use std::path::Path;

use super::{GeneratorError, GeneratorMetadata, GeneratorModule, GeneratorResult};
use crate::parser::vk_types::IncludeStatement;

/// Generator module for Vulkan includes
pub struct IncludeGenerator;

impl Default for IncludeGenerator {
    fn default() -> Self {
        Self::new()
    }
}

impl IncludeGenerator {
    pub fn new() -> Self {
        Self
    }

    /// Generate Rust code for include dependencies
    fn generate_includes(&self, includes: &[IncludeStatement]) -> String {
        let mut code = String::new();

        code.push_str("// === SYSTEM INCLUDES AND DEPENDENCIES ===\n\n");

        // Map C includes to Rust dependencies and use statements
        let mut rust_uses = Vec::new();
        let mut comments = Vec::new();

        for include in includes {
            match include.filename.as_str() {
                "stdint.h" => {
                    comments.push(format!(
                        "// {}: Standard integer types (mapped to Rust primitives)",
                        include.filename
                    ));
                }
                "stddef.h" => {
                    comments.push(format!(
                        "// {}: Standard definitions (size_t, etc.)",
                        include.filename
                    ));
                    // c_void handled by assembler imports
                }
                "string.h" => {
                    comments.push(format!(
                        "// {}: String handling functions",
                        include.filename
                    ));
                    rust_uses.push("use std::ffi::{CStr, CString};".to_string());
                }
                "stdlib.h" => {
                    comments.push(format!(
                        "// {}: Standard library functions",
                        include.filename
                    ));
                }
                _ if include.filename.contains("platform") => {
                    comments.push(format!(
                        "// {}: Platform-specific definitions",
                        include.filename
                    ));
                    // c_void handled by assembler imports
                }
                _ if include.filename.contains("vulkan") => {
                    comments.push(format!("// {}: Vulkan header dependency", include.filename));
                }
                _ => {
                    // Source line not available in simplified intermediate types
                    // if let Some(line) = include.source_line {
                    //     comments.push(format!(
                    //         "// {}: External dependency (line {})",
                    //         include.name, line
                    //     ));
                    // } else {
                    comments.push(format!("// {}: External dependency", include.filename));
                    // }
                }
            }
        }

        // Add comments about original includes
        for comment in comments {
            code.push_str(&format!("{}\n", comment));
        }
        code.push('\n');

        // Add Rust use statements (deduplicated)
        rust_uses.sort();
        rust_uses.dedup();
        let uses_not_empty = !rust_uses.is_empty();
        for use_stmt in rust_uses {
            code.push_str(&format!("{}\n", use_stmt));
        }

        if uses_not_empty {
            code.push('\n');
        }

        code
    }
}

impl GeneratorModule for IncludeGenerator {
    fn name(&self) -> &str {
        "IncludeGenerator"
    }

    fn input_files(&self) -> Vec<String> {
        vec!["includes.json".to_string()]
    }

    fn output_file(&self) -> String {
        "includes.rs".to_string()
    }

    fn dependencies(&self) -> Vec<String> {
        Vec::new() // Includes don't depend on other modules
    }

    fn generate(&self, input_dir: &Path, output_dir: &Path) -> GeneratorResult<()> {
        // Read input file
        let input_path = input_dir.join("includes.json");
        let content =
            fs::read_to_string(&input_path).map_err(|_| GeneratorError::MissingInput {
                path: input_path.display().to_string(),
            })?;

        let includes: Vec<IncludeStatement> = serde_json::from_str(&content)?;

        // Generate code
        let mut code = String::new();

        // File header
        code.push_str(
            "// Generated include handling and platform dependencies\n\
            //\n\
            // This file contains platform-specific type definitions and\n\
            // dependency mappings derived from C includes in the Vulkan specification.\n\
            // Do not edit this file directly.\n\n",
        );

        // Generate include mappings as comments
        code.push_str(&self.generate_includes(&includes));

        // Platform-specific types are handled by the TypeGenerator
        // (external types with requires= attributes get opaque pointer aliases).

        // Write output file
        let output_path = output_dir.join(self.output_file());
        fs::write(output_path, code)?;

        Ok(())
    }

    fn metadata(&self) -> GeneratorMetadata {
        GeneratorMetadata {
            defined_types: Vec::new(),
            used_types: vec![
                "c_void".to_string(),
                "CStr".to_string(),
                "CString".to_string(),
            ],
            has_forward_declarations: false,
            priority: 5, // Very early, before most other modules
        }
    }
}