use crate::parser::vk_types::ExtensionDefinition;
use std::fs;
use std::path::Path;
use super::{GeneratorError, GeneratorMetadata, GeneratorModule, GeneratorResult};
pub struct ExtensionGenerator;
impl Default for ExtensionGenerator {
fn default() -> Self {
Self::new()
}
}
impl ExtensionGenerator {
pub fn new() -> Self {
Self
}
fn generate_extension(&self, ext: &ExtensionDefinition) -> String {
let mut code = String::new();
if let Some(line) = ext.source_line {
code.push_str(&format!(
"/// Vulkan extension: {} (from line {})\n",
ext.name, line
));
} else {
code.push_str(&format!("/// Vulkan extension: {}\n", ext.name));
}
if let Some(platform) = &ext.platform {
code.push_str(&format!("/// Platform: {}\n", platform));
}
if let Some(author) = &ext.author {
code.push_str(&format!("/// Author: {}\n", author));
}
if ext.provisional.is_some() {
code.push_str("/// Status: Provisional\n");
}
if let Some(deprecated) = &ext.deprecated {
code.push_str(&format!("/// Deprecated: {}\n", deprecated));
}
if let Some(promoted_to) = &ext.promotedto {
code.push_str(&format!("/// Promoted to: {}\n", promoted_to));
}
let const_name = format!(
"{}_EXTENSION_NAME",
ext.name.to_uppercase().replace("VK_", "")
);
code.push_str(&format!(
"pub const {}: &str = \"{}\";\n",
const_name, ext.name
));
if let Some(number) = &ext.number {
let number_const = format!(
"{}_SPEC_VERSION",
ext.name.to_uppercase().replace("VK_", "")
);
code.push_str(&format!("pub const {}: u32 = {};\n", number_const, number));
}
code.push('\n');
code
}
fn generate_extension_function_types(&self, _extensions: &[ExtensionDefinition]) -> String {
String::new()
}
fn generate_extension_utilities(&self) -> String {
String::new()
}
}
impl GeneratorModule for ExtensionGenerator {
fn name(&self) -> &str {
"ExtensionGenerator"
}
fn input_files(&self) -> Vec<String> {
vec!["extensions.json".to_string()]
}
fn output_file(&self) -> String {
"extensions.rs".to_string()
}
fn dependencies(&self) -> Vec<String> {
vec![
"TypeGenerator".to_string(),
"ConstantGenerator".to_string(),
"StructGenerator".to_string(),
"FunctionGenerator".to_string(),
]
}
fn generate(&self, input_dir: &Path, output_dir: &Path) -> GeneratorResult<()> {
let input_path = input_dir.join("extensions.json");
let content =
fs::read_to_string(&input_path).map_err(|_| GeneratorError::MissingInput {
path: input_path.display().to_string(),
})?;
let extensions: Vec<ExtensionDefinition> = serde_json::from_str(&content)?;
let mut code = String::new();
code.push_str(
"// Generated Vulkan extension definitions\n\
//\n\
// This file contains extension constants, feature structures,\n\
// and utility functions for Vulkan extensions.\n\
// Do not edit this file directly.\n\n",
);
code.push_str("// === EXTENSION DEFINITIONS ===\n\n");
for extension in &extensions {
code.push_str(&self.generate_extension(extension));
}
code.push_str(&self.generate_extension_function_types(&extensions));
code.push_str(&self.generate_extension_utilities());
let output_path = output_dir.join(self.output_file());
fs::write(output_path, code)?;
Ok(())
}
fn metadata(&self) -> GeneratorMetadata {
GeneratorMetadata {
defined_types: vec![
"VkExtensionProperties".to_string(),
"PFN_vkGetInstanceProcAddr".to_string(),
"PFN_vkGetDeviceProcAddr".to_string(),
],
used_types: vec![
"VkStructureType".to_string(),
"VkInstance".to_string(),
"VkDevice".to_string(),
"c_char".to_string(),
"c_void".to_string(),
],
has_forward_declarations: false,
priority: 20, }
}
}