use crate::context::CodegenContext;
use crate::naming::{escape_reserved, to_snake_case};
use crate::schema::*;
use crate::type_map::{ConversionKind, MappedType};
use super::classes::is_struct_owned;
use super::properties;
pub fn emit_out_param_var_decl(out: &mut String, param: &ParamInfo, mapped: &MappedType) {
let pname = escape_reserved(&to_snake_case(¶m.name));
match mapped.ffi_to_rust {
ConversionKind::StructOpaque => {
out.push_str(&format!(" let mut {pname}_buf = vec![0u8; 256];\n"));
}
ConversionKind::StringUtf8 => {
out.push_str(&format!(" let mut {pname}_buf = vec![0u8; 512];\n"));
out.push_str(&format!(" let mut {pname}_len: u32 = 0;\n"));
}
ConversionKind::ObjectRef => {
out.push_str(&format!(
" let mut {pname} = rusteal_core::UObjectHandle::null();\n"
));
}
ConversionKind::EnumCast => {
out.push_str(&format!(" let mut {pname}: {} = 0;\n", mapped.rust_ffi_type));
}
_ => {
let default = properties::default_value_for(&mapped.rust_ffi_type);
out.push_str(&format!(" let mut {pname} = {default};\n"));
}
}
}
pub fn emit_inout_string_buf_decl(out: &mut String, param: &ParamInfo, mapped: &MappedType) {
if mapped.ffi_to_rust == ConversionKind::StringUtf8 {
let pname = escape_reserved(&to_snake_case(¶m.name));
out.push_str(&format!(" let mut {pname}_buf = vec![0u8; 512];\n"));
out.push_str(&format!(" let mut {pname}_len: u32 = 0;\n"));
}
}
pub fn emit_out_param_conversion(
out: &mut String,
param: &ParamInfo,
mapped: &MappedType,
ctx: &CodegenContext,
) -> String {
let pname = escape_reserved(&to_snake_case(¶m.name));
match mapped.ffi_to_rust {
ConversionKind::ObjectRef => {
format!("unsafe {{ rusteal_core::UObjectRef::from_raw({pname}) }}")
}
ConversionKind::StringUtf8 => {
out.push_str(&format!(" {pname}_buf.truncate({pname}_len as usize);\n"));
out.push_str(&format!(
" let {pname}_str = String::from_utf8_lossy(&{pname}_buf).into_owned();\n"
));
format!("{pname}_str")
}
ConversionKind::EnumCast => {
let rt = &mapped.rust_type;
let actual_repr = param.enum_name.as_deref()
.and_then(|en| ctx.enum_actual_repr(en))
.unwrap_or(&mapped.rust_ffi_type);
out.push_str(&format!(
" let {pname}_enum = {rt}::from_value({pname} as {actual_repr}).expect(\"unknown enum value\");\n"
));
format!("{pname}_enum")
}
ConversionKind::StructOpaque => {
if is_struct_owned(param.struct_name.as_deref(), ctx) {
out.push_str(&format!(
" let {pname}_owned = rusteal_core::OwnedStruct::from_bytes({pname}_buf);\n"
));
format!("{pname}_owned")
} else {
out.push_str(&format!(" let {pname}_ptr = {pname}_buf.as_ptr();\n"));
out.push_str(&format!(" std::mem::forget({pname}_buf);\n"));
format!("{pname}_ptr")
}
}
ConversionKind::IntCast => {
let rt = &mapped.rust_type;
format!("{pname} as {rt}")
}
ConversionKind::FName => {
pname.to_string()
}
_ => {
pname.to_string()
}
}
}
pub fn emit_return_expr(out: &mut String, return_parts: &[String]) {
match return_parts.len() {
0 => {},
1 => out.push_str(&format!(" {}\n", return_parts[0])),
_ => out.push_str(&format!(" ({})\n", return_parts.join(", "))),
}
}