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