1
raylib-ffi/build/wrap/enums.rs

111 lines
3.7 KiB
Rust

use std::path::PathBuf;
use super::raylib_api::RayLibApiDefinition;
/// A mapping of enum names to the number of tokens to pop off the variant prefix
/// (C enums tend to have prefixes to avoid name collisions)
fn get_prefix_len(name: &str) -> usize {
// Some enums have more than one prefix token
match name {
"CubemapLayout" => 2,
"GamepadAxis" => 2,
"GamepadButton" => 2,
"MaterialMapIndex" => 2,
"MouseButton" => 2,
"MouseCursor" => 2,
"PixelFormat" => 2,
"ShaderAttributeDataType" => 2,
"ShaderLocationIndex" => 2,
"ShaderUniformDataType" => 2,
"TextureFilter" => 2,
"TextureWrap" => 2,
_ => 1,
}
}
/// Gets a list of enum names for bindgen to skip.
/// We are manually binding them to Rust here, so there is no need to double-translate
pub fn get_blocked_enum_names() -> Vec<String> {
vec![
"BlendMode",
"CameraMode",
"CameraProjection",
"ConfigFlags",
"CubemapLayout",
"FontType",
"GamepadAxis",
"GamepadButton",
"Gesture",
"KeyboardKey",
"MaterialMapIndex",
"MouseButton",
"MouseCursor",
"NPatchLayout",
"PixelFormat",
"ShaderAttributeDataType",
"ShaderLocationIndex",
"ShaderUniformDataType",
"TextureFilter",
"TextureWrap",
"TraceLogLevel"
].into_iter().map(|s| s.to_string()).collect()
}
pub fn wrap_exposed_enums(api_defs: RayLibApiDefinition) {
// Allocate an output buffer for lines
let mut lines = Vec::new();
// Handle each enum
for en in api_defs.enums {
// Write a doc comment with raylib's provided enum description
lines.push("".to_string());
lines.push(format!("/// {}", en.description));
// Write the enum declaration
lines.push("#[repr(C)]".to_string());
lines.push("#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]".to_string());
lines.push(format!("pub enum {} {{", en.name));
// Write each enum variant
for variant in en.values {
// For now, we have to skip `KEY_MENU` because it shares a value with `KEY_R`
if variant.name == "KEY_MENU" {
continue;
}
// Write a doc comment with raylib's provided variant description
lines.push(format!("\t/// {}", variant.description));
// Transform the name into a valid Rust identifier
let name_parts = variant.name.split('_').collect::<Vec<_>>();
// Ignore the prefix tokens
let name_parts = &name_parts[get_prefix_len(&en.name)..];
// Capitalize and join
let mut name = String::new();
for part in name_parts.iter() {
let mut chars = part.chars();
name.push(chars.next().unwrap_or(' ').to_ascii_uppercase());
name.push_str(chars.as_str().to_ascii_lowercase().as_str());
}
// Write the variant declaration
lines.push(format!("\t{} = {},", name, variant.value));
}
// Close the enum declaration
lines.push("}".to_string());
// Write a conversion function
lines.push(format!("impl Into<usize> for {} {{", en.name));
lines.push(format!("\tfn into(self) -> usize {{"));
lines.push(format!("\t\tself as usize"));
lines.push(format!("\t}}"));
lines.push(format!("}}"));
}
// Write the output file
let out_path = PathBuf::from(std::env::var("OUT_DIR").unwrap());
let output = lines.join("\n");
std::fs::write(out_path.join("enums.rs"), output).unwrap();
}