rusteal_codegen/rust_gen/
structs.rs1use crate::context::CodegenContext;
2use crate::schema::StructInfo;
3
4use super::properties::{self, PropertyContext};
5
6pub fn generate_struct(s: &StructInfo, ctx: &CodegenContext) -> String {
7 let mut out = String::with_capacity(2048);
8 let name = &s.cpp_name;
9 let stripped = &s.name;
10
11 out.push_str("use super::*;\n");
12 out.push_str("use rusteal_core::{UeClass, UeStruct, UeEnum};\n");
13
14 let current_module = ctx
15 .package_to_module
16 .get(&s.package)
17 .map(|s| s.as_str())
18 .unwrap_or("");
19
20 let mut modules: Vec<&String> = ctx.enabled_modules.iter().collect();
21 modules.sort();
22
23 for module in modules {
24 if module != current_module {
25 if let Some(feature) = ctx.feature_for_module(module) {
26 out.push_str(&format!("#[cfg(feature = \"{feature}\")]\n"));
27 }
28
29 out.push_str(&format!("use crate::{module}::*;\n"));
30 }
31 }
32
33 out.push('\n');
34
35 out.push_str(&format!(
36 "/// Opaque UE struct `{name}`. Layout managed by C++ side.\n\
37 pub struct {name};\n\n"
38 ));
39
40 if s.has_static_struct {
41 let name_bytes = stripped.as_bytes();
42 let name_len = name_bytes.len();
43 let byte_lit = format!("b\"{stripped}\\0\"");
44
45 out.push_str(&format!(
46 "impl rusteal_core::UeStruct for {name} {{\n\
47 \x20 fn static_struct() -> rusteal_core::UStructHandle {{\n\
48 \x20 static CACHE: std::sync::OnceLock<rusteal_core::UStructHandle> = std::sync::OnceLock::new();\n\
49 \x20 *CACHE.get_or_init(|| unsafe {{\n\
50 \x20 rusteal_core::ffi_dispatch::reflection_find_struct({byte_lit}.as_ptr(), {name_len})\n\
51 \x20 }})\n\
52 \x20 }}\n\
53 }}\n\n"
54 ));
55
56 let (_, deduped_props) = properties::collect_deduped_properties(&s.props, Some(ctx));
57
58 if !deduped_props.is_empty() {
59 let pctx = PropertyContext {
60 find_prop_fn: "find_struct_property".to_string(),
61 handle_expr: format!("{name}::static_struct()"),
62 pre_access: String::new(),
63 container_expr: "self.as_ptr()".to_string(),
64 };
65
66 let trait_name = format!("{name}Ext");
67
68 let no_suppress = std::collections::HashSet::new();
69 let mut body_buf = String::new();
70
71 for prop in &deduped_props {
72 properties::generate_property(&mut body_buf, prop, &pctx, ctx, &no_suppress);
73 }
74
75 out.push_str(&format!("pub trait {trait_name} {{\n"));
76
77 for line in body_buf.lines() {
78 if line.starts_with(" fn ") && line.ends_with(" {") {
79 out.push_str(&line[..line.len() - 2]);
80 out.push_str(";\n");
81 }
82 }
83
84 out.push_str("}\n\n");
85
86 out.push_str(&format!(
87 "impl {trait_name} for rusteal_core::UStructRef<{name}> {{\n"
88 ));
89
90 out.push_str(&body_buf);
91 out.push_str("}\n");
92 }
93 }
94
95 out
96}