Skip to main content

rusteal_codegen/rust_gen/
param_helpers.rs

1// Shared parameter handling helpers for native codegen (classes.rs).
2//
3// Extracts duplicated logic for output variable declarations, return value
4// conversion, and return expression formatting.
5
6use crate::context::CodegenContext;
7use crate::naming::{escape_reserved, to_snake_case};
8use crate::schema::*;
9use crate::type_map::{ConversionKind, MappedType};
10
11use super::classes::is_struct_owned;
12use super::properties;
13
14// ---------------------------------------------------------------------------
15// Output variable declarations
16// ---------------------------------------------------------------------------
17
18/// Emit `let mut` declarations for a scalar Out parameter.
19pub fn emit_out_param_var_decl(out: &mut String, param: &ParamInfo, mapped: &MappedType) {
20    let pname = escape_reserved(&to_snake_case(&param.name));
21    match mapped.ffi_to_rust {
22        ConversionKind::StructOpaque => {
23            out.push_str(&format!("        let mut {pname}_buf = vec![0u8; 256];\n"));
24        }
25        ConversionKind::StringUtf8 => {
26            out.push_str(&format!("        let mut {pname}_buf = vec![0u8; 512];\n"));
27            out.push_str(&format!("        let mut {pname}_len: u32 = 0;\n"));
28        }
29        ConversionKind::ObjectRef => {
30            out.push_str(&format!(
31                "        let mut {pname} = rusteal_core::UObjectHandle::null();\n"
32            ));
33        }
34        ConversionKind::EnumCast => {
35            out.push_str(&format!("        let mut {pname}: {} = 0;\n", mapped.rust_ffi_type));
36        }
37        _ => {
38            let default = properties::default_value_for(&mapped.rust_ffi_type);
39            out.push_str(&format!("        let mut {pname} = {default};\n"));
40        }
41    }
42}
43
44/// Emit output buffer declarations for InOut string/text parameters.
45pub fn emit_inout_string_buf_decl(out: &mut String, param: &ParamInfo, mapped: &MappedType) {
46    if mapped.ffi_to_rust == ConversionKind::StringUtf8 {
47        let pname = escape_reserved(&to_snake_case(&param.name));
48        out.push_str(&format!("        let mut {pname}_buf = vec![0u8; 512];\n"));
49        out.push_str(&format!("        let mut {pname}_len: u32 = 0;\n"));
50    }
51}
52
53// ---------------------------------------------------------------------------
54// Return value conversion (Out/InOut parameters)
55// ---------------------------------------------------------------------------
56
57/// Emit return conversion for a scalar Out/InOut parameter.
58/// Returns the expression string to include in the return tuple.
59pub fn emit_out_param_conversion(
60    out: &mut String,
61    param: &ParamInfo,
62    mapped: &MappedType,
63    ctx: &CodegenContext,
64) -> String {
65    let pname = escape_reserved(&to_snake_case(&param.name));
66    match mapped.ffi_to_rust {
67        ConversionKind::ObjectRef => {
68            format!("unsafe {{ rusteal_core::ObjectPointer::from_object_handle({pname}) }}")
69        }
70        ConversionKind::StringUtf8 => {
71            out.push_str(&format!("        {pname}_buf.truncate({pname}_len as usize);\n"));
72            out.push_str(&format!(
73                "        let {pname}_str = String::from_utf8_lossy(&{pname}_buf).into_owned();\n"
74            ));
75            format!("{pname}_str")
76        }
77        ConversionKind::EnumCast => {
78            let rt = &mapped.rust_type;
79            let actual_repr = param.enum_name.as_deref()
80                .and_then(|en| ctx.enum_actual_repr(en))
81                .unwrap_or(&mapped.rust_ffi_type);
82            out.push_str(&format!(
83                "        let {pname}_enum = {rt}::from_value({pname} as {actual_repr}).expect(\"unknown enum value\");\n"
84            ));
85            format!("{pname}_enum")
86        }
87        ConversionKind::StructOpaque => {
88            if is_struct_owned(param.struct_name.as_deref(), ctx) {
89                out.push_str(&format!(
90                    "        let {pname}_owned = rusteal_core::OwnedStruct::from_bytes({pname}_buf);\n"
91                ));
92                format!("{pname}_owned")
93            } else {
94                out.push_str(&format!("        let {pname}_ptr = {pname}_buf.as_ptr();\n"));
95                out.push_str(&format!("        std::mem::forget({pname}_buf);\n"));
96                format!("{pname}_ptr")
97            }
98        }
99        ConversionKind::IntCast => {
100            let rt = &mapped.rust_type;
101            format!("{pname} as {rt}")
102        }
103        ConversionKind::FName => {
104            pname.to_string()
105        }
106        _ => {
107            pname.to_string()
108        }
109    }
110}
111
112/// Emit the final return expression from a list of return parts.
113pub fn emit_return_expr(out: &mut String, return_parts: &[String]) {
114    match return_parts.len() {
115        0 => {},
116        1 => out.push_str(&format!("        {}\n", return_parts[0])),
117        _ => out.push_str(&format!("        ({})\n", return_parts.join(", "))),
118    }
119}