Skip to main content

rusteal_codegen/
defaults.rs

1use crate::context::CodegenContext;
2use crate::schema::ParamInfo;
3use crate::type_map::{ConversionKind, MappedType};
4
5pub fn parse_default_literal(
6    param: &ParamInfo,
7    mapped: &MappedType,
8    ctx: &CodegenContext,
9) -> Option<String> {
10    let default_str = param.default.as_deref()?;
11
12    if mapped.rust_to_ffi == ConversionKind::StructOpaque {
13        return None;
14    }
15
16    match param.prop_type.as_str() {
17        "BoolProperty" => parse_bool_default(default_str),
18        "FloatProperty" => parse_float_default(default_str, "f32"),
19        "DoubleProperty" => parse_float_default(default_str, "f64"),
20        "IntProperty" => parse_int_default(default_str, "i32"),
21        "Int8Property" => parse_int_default(default_str, "i8"),
22        "Int16Property" => parse_int_default(default_str, "i16"),
23        "Int64Property" => parse_int_default(default_str, "i64"),
24        "ByteProperty" => {
25            if param.enum_name.is_some() {
26                parse_enum_default(default_str, param, ctx)
27            } else {
28                parse_int_default(default_str, "u8")
29            }
30        }
31        "UInt16Property" => parse_int_default(default_str, "u16"),
32        "UInt32Property" => parse_int_default(default_str, "u32"),
33        "UInt64Property" => parse_int_default(default_str, "u64"),
34        "EnumProperty" => parse_enum_default(default_str, param, ctx),
35        "ObjectProperty" | "ClassProperty" | "SoftObjectProperty" | "WeakObjectProperty"
36        | "InterfaceProperty" => parse_object_default(default_str, mapped),
37        "StrProperty" | "TextProperty" => parse_string_default(default_str),
38        "NameProperty" => parse_fname_default(default_str),
39        _ => None,
40    }
41}
42
43fn parse_bool_default(s: &str) -> Option<String> {
44    match s {
45        "true" | "True" => Some("true".into()),
46        "false" | "False" => Some("false".into()),
47        _ => None,
48    }
49}
50
51fn parse_float_default(s: &str, suffix: &str) -> Option<String> {
52    let _: f64 = s.parse().ok()?;
53
54    if s.contains('.') {
55        Some(format!("{s}{suffix}"))
56    } else {
57        Some(format!("{s}.0{suffix}"))
58    }
59}
60
61fn parse_int_default(s: &str, suffix: &str) -> Option<String> {
62    let _: i128 = s.parse().ok()?;
63    Some(format!("{s}{suffix}"))
64}
65
66fn parse_object_default(s: &str, mapped: &MappedType) -> Option<String> {
67    if s == "None" {
68        if mapped.rust_to_ffi == ConversionKind::ObjectRef {
69            Some("unsafe { rusteal_core::ObjectPointer::from_object_handle(rusteal_core::UObjectHandle::null()) }".into())
70        } else {
71            Some("rusteal_core::UObjectHandle::null()".into())
72        }
73    } else {
74        None
75    }
76}
77
78fn parse_string_default(s: &str) -> Option<String> {
79    let escaped = s.replace('\\', "\\\\").replace('"', "\\\"");
80    Some(format!("\"{escaped}\""))
81}
82
83fn parse_fname_default(s: &str) -> Option<String> {
84    if s.is_empty() || s == "None" {
85        Some("rusteal_core::FNameHandle(0)".into())
86    } else {
87        None
88    }
89}
90
91fn parse_enum_default(s: &str, param: &ParamInfo, ctx: &CodegenContext) -> Option<String> {
92    let enum_name = param.enum_name.as_deref()?;
93    let enum_info = ctx.enums.get(enum_name)?;
94
95    let actual_repr = ctx.enum_actual_repr(enum_name).unwrap_or("u8");
96
97    for (variant_name, value) in &enum_info.pairs {
98        if variant_name == s || variant_name.ends_with(&format!("::{s}")) {
99            return Some(format!(
100                "{enum_name}::from_value({value} as {actual_repr}).expect(\"invalid enum default for {enum_name}\")"
101            ));
102        }
103    }
104
105    None
106}