Skip to content

Commit

Permalink
Improve Rust enum translations
Browse files Browse the repository at this point in the history
  • Loading branch information
ewpratten committed Apr 12, 2023
1 parent dda9be8 commit 961550b
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 12 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
"${workspaceFolder}/third_party/raylib/src",
],
"python.formatting.provider": "yapf",
"liveServer.settings.root": "/target/doc",
}
23 changes: 23 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "cargo",
"command": "build",
"problemMatcher": [
"$rustc"
],
"group": "build",
"label": "Compile Library"
},
{
"type": "cargo",
"command": "doc",
"problemMatcher": [
"$rustc"
],
"group": "build",
"label": "Build Docs"
}
]
}
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "raylib-ffi"
version = "4.5.2"
version = "4.5.3"
authors = ["Evan Pratten <[email protected]>"]
edition = "2021"
description = "Automatic raw Rust bindings to raylib"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ cargo run --example basic

## Versioning policy

`raylib-ffi` follow [SemVer](https://semver.org/).
`raylib-ffi` follows [SemVer](https://semver.org/).

The major and minor version numbers of a `raylib-ffi` will always match the version of raylib it was built against. The patch version may be incremented if a rust-only fix is needed at any point.
40 changes: 32 additions & 8 deletions build/bind.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::path::PathBuf;

use crate::wrap::enums::get_blocked_enum_names;

/// Compiles raylib
pub fn compile_raylib(raylib_path: &str) {
// Construct a config for running cmake
Expand All @@ -23,9 +25,18 @@ pub fn compile_raylib(raylib_path: &str) {
let destination = cmake_config.build();

// Tell cargo where the libraries might be
println!("cargo:rustc-link-search=native={}", destination.join("lib").display());
println!("cargo:rustc-link-search=native={}", destination.join("lib32").display());
println!("cargo:rustc-link-search=native={}", destination.join("lib64").display());
println!(
"cargo:rustc-link-search=native={}",
destination.join("lib").display()
);
println!(
"cargo:rustc-link-search=native={}",
destination.join("lib32").display()
);
println!(
"cargo:rustc-link-search=native={}",
destination.join("lib64").display()
);
}

/// Links libraries
Expand Down Expand Up @@ -62,16 +73,29 @@ pub fn link_libs() {

/// Generates `bindings.rs` file
pub fn generate_bindings(header_file: &str) {
// Generate the data
let bindings = bindgen::Builder::default()
// Construct a builder for generating bindings
let mut builder = bindgen::Builder::default()
.header(header_file)
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate()
.expect("Unable to generate bindings");
.blocklist_item("DEG2RAD")
.blocklist_item("PI")
.blocklist_item("RAD2DEG")
.blocklist_item("__GNUC_VA_LIST")
.blocklist_item("__bool_true_false_are_defined")
.blocklist_item("false_")
.blocklist_item("true_");

// Deny all blocked enums
for enum_name in get_blocked_enum_names() {
builder = builder.blocklist_type(format!("{}.*", enum_name));
}

// Generate the bindings
let bindings = builder.generate().expect("Unable to generate bindings");

// Write `src/bindings.rs`
let out_path = PathBuf::from(std::env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}
}
61 changes: 59 additions & 2 deletions build/wrap/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,55 @@ 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();
Expand Down Expand Up @@ -29,11 +78,14 @@ pub fn wrap_exposed_enums(api_defs: RayLibApiDefinition) {

// 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());
name.push_str(chars.as_str().to_ascii_lowercase().as_str());
}

// Write the variant declaration
Expand All @@ -43,11 +95,16 @@ pub fn wrap_exposed_enums(api_defs: RayLibApiDefinition) {
// 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();

}

0 comments on commit 961550b

Please sign in to comment.