rusteal_codegen/cpp_gen/
fill_table.rs1use std::collections::BTreeMap;
4
5use crate::context::FuncEntry;
6use crate::cpp_gen::wrapper::cpp_wrapper_name;
7
8pub fn generate_fill_table(
10 prefix: &str,
11 entries: &[FuncEntry],
12 _by_class: &BTreeMap<(String, String), Vec<&FuncEntry>>,
13) -> String {
14 let mut out = String::with_capacity(entries.len() * 80 + 1024);
15
16 out.push_str("// Auto-generated by rusteal-codegen. Do not edit.\n\n");
17 out.push_str("#include \"RustealFuncIds.h\"\n\n");
18
19 out.push_str("// Forward declarations of wrapper functions\n");
21 for entry in entries {
22 let c_name = cpp_wrapper_name(prefix, &entry.class_name, &entry.func_name);
23 out.push_str(&format!("extern \"C\" uint32_t {c_name}(...);\n"));
24 }
25 out.push('\n');
26
27 out.push_str("static void* GRustealFuncTable[RustealFuncId::FUNC_COUNT];\n\n");
29
30 out.push_str(&format!("void {prefix}RustealFillFuncTable() {{\n"));
32 for entry in entries {
33 let const_name =
34 crate::rust_gen::func_ids::func_id_const_name(&entry.class_name, &entry.func_name);
35 let c_name = cpp_wrapper_name(prefix, &entry.class_name, &entry.func_name);
36 out.push_str(&format!(
37 " GRustealFuncTable[RustealFuncId::{const_name}] = (void*)&{c_name};\n"
38 ));
39 }
40 out.push_str("}\n\n");
41
42 out.push_str(&format!("void** {prefix}RustealGetFuncTable() {{\n"));
44 out.push_str(" return GRustealFuncTable;\n");
45 out.push_str("}\n\n");
46
47 out.push_str(&format!(
48 "uint32_t {prefix}RustealGetFuncCount() {{\n return RustealFuncId::FUNC_COUNT;\n}}\n"
49 ));
50
51 out
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 fn entry(func_id: u32, class_name: &str, func_name: &str) -> FuncEntry {
59 let func = serde_json::from_value(serde_json::json!({
60 "name": func_name,
61 "func_flags": 0,
62 }))
63 .unwrap();
64 FuncEntry {
65 func_id,
66 module_name: "engine".to_string(),
67 class_name: class_name.to_string(),
68 func_name: func_name.to_string(),
69 rust_func_name: func_name.to_string(),
70 func,
71 cpp_class_name: format!("A{class_name}"),
72 header: String::new(),
73 }
74 }
75
76 #[test]
77 fn game_library_keeps_the_unprefixed_names() {
78 let code = generate_fill_table("", &[entry(0, "Actor", "GetOwner")], &BTreeMap::new());
79 assert!(code.contains("void RustealFillFuncTable()"), "{code}");
80 assert!(code.contains("void** RustealGetFuncTable()"), "{code}");
81 assert!(code.contains("uint32_t RustealGetFuncCount()"), "{code}");
82 assert!(code.contains("= (void*)&Rusteal_Actor_GetOwner;"), "{code}");
83 }
84
85 #[test]
86 fn plugin_library_prefixes_every_symbol() {
87 let code =
88 generate_fill_table("Inventory_", &[entry(0, "Actor", "GetOwner")], &BTreeMap::new());
89 assert!(code.contains("extern \"C\" uint32_t Inventory_Rusteal_Actor_GetOwner(...);"), "{code}");
90 assert!(code.contains("void Inventory_RustealFillFuncTable()"), "{code}");
91 assert!(code.contains("void** Inventory_RustealGetFuncTable()"), "{code}");
92 assert!(code.contains("uint32_t Inventory_RustealGetFuncCount()"), "{code}");
93 assert!(!code.contains(" RustealFillFuncTable()"), "{code}");
94 }
95}