summaryrefslogtreecommitdiff
path: root/codegen/bindings.rs
blob: 5fdfaf36192cc298134417ccb7cfdac5538c0854 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use std::error::Error;
use std::path::Path;

use bindgen::callbacks::ParseCallbacks;
use bindgen::{CodegenConfig, MacroTypeVariation};

pub fn generate_bindings(dest_file: &Path) -> Result<(), Box<dyn Error>>
{
    println!("cargo:rerun-if-changed=gl.h");

    let bindings = bindgen::Builder::default()
        .header("gl.h")
        .default_macro_constant_type(MacroTypeVariation::Signed)
        .with_codegen_config(CodegenConfig::all() & !CodegenConfig::FUNCTIONS)
        .allowlist_type("GL.*")
        .allowlist_type("_cl_.*")
        .allowlist_var("GL_.*")
        .blocklist_item("GL_Z4.*")
        .blocklist_item("GL_Z6.*")
        .parse_callbacks(Box::new(Callbacks))
        .generate()?;

    bindings.write_to_file(dest_file)?;

    Ok(())
}

#[derive(Debug)]
struct Callbacks;

impl ParseCallbacks for Callbacks
{
    fn item_name(&self, original_item_name: &str) -> Option<String>
    {
        let stripped = original_item_name.strip_prefix("GL_")?;

        if stripped.starts_with(|character: char| character.is_ascii_digit()) {
            let digit_cnt = stripped
                .chars()
                .filter(|character| character.is_ascii_digit())
                .count();

            let digits = stripped
                .chars()
                .take_while(|character| character.is_ascii_digit())
                .map(|character| match character {
                    '0' => "zero",
                    '1' => "one",
                    '2' => "two",
                    '3' => "three",
                    '4' => "four",
                    '5' => "five",
                    '6' => "six",
                    '7' => "seven",
                    '8' => "eight",
                    '9' => "nine",
                    _ => unreachable!(),
                });

            return Some(
                digits
                    .map(|digit| digit.chars())
                    .flatten()
                    .map(|character| character.to_ascii_uppercase())
                    .chain(stripped.chars().skip(digit_cnt))
                    .collect::<String>(),
            );
        }

        Some(stripped.to_string())
    }
}