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