rusty_bind_parser/swift/
function_helper.rs1use std::fmt::Display;
2
3use convert_case::{Case, Casing};
4
5use crate::binding_types::{Arg, Function, RustWrapperType, WrapperType};
6use crate::extern_module_translator::Exceptions;
7use crate::swift::templates::TargetLanguageTypeName;
8use crate::EXPORTED_SYMBOLS_PREFIX;
9
10pub struct FunctionHelperVirtual {
11 pub function_name: String,
12 pub generated_args: String,
13 pub generated_function_body: Vec<String>,
14 pub generated_virtual_function_signature: String,
15 pub return_type: Option<WrapperType>,
16 pub arg_names: Vec<String>,
17 class_name: String,
18}
19
20impl FunctionHelperVirtual {
21 fn create_list_of_arguments_translated_to_cpp(function: &Function) -> Vec<String> {
22 let mut generated_args = function
23 .arguments
24 .iter()
25 .skip(1)
26 .map(|arg| match &arg.typ {
27 WrapperType {
28 rust_type: RustWrapperType::Primitive | RustWrapperType::FieldlessEnum,
29 ..
30 } => format!("_ {}: {}", arg.arg_name, arg.typ.wrapper_name),
31 _ => format!("_ {}: UnsafeMutableRawPointer", arg.arg_name),
32 })
33 .collect::<Vec<String>>();
34 generated_args.insert(0, "_ _self: AnyObject".to_owned());
35 generated_args
36 }
37
38 fn create_function_signature(function: &Function) -> String {
39 function
40 .arguments
41 .iter()
42 .skip(1)
43 .map(|arg| format!("_ {}: {}", arg.arg_name, arg.typ.get_name()))
44 .collect::<Vec<String>>()
45 .join(", ")
46 }
47
48 fn create_function_body(function: &Function) -> Vec<String> {
49 function
50 .arguments
51 .iter()
52 .skip(1)
53 .map(|arg| {
54 let inner_type_name = arg.typ.get_name();
55 let arg_name = &arg.arg_name;
56 format!("{inner_type_name}({arg_name})")
57 })
58 .collect()
59 }
60
61 pub fn from_virtual_function(function: &Function, class_name: &str) -> Self {
82 let generated_args =
83 FunctionHelperVirtual::create_list_of_arguments_translated_to_cpp(function);
84 let generated_args = generated_args.join(", ");
85 let generated_virtual_function_signature =
86 FunctionHelperVirtual::create_function_signature(function);
87 let generated_function_body: Vec<String> =
88 FunctionHelperVirtual::create_function_body(function);
89 let function_name = function.name.to_string();
90 let arg_names = function
91 .arguments
92 .iter()
93 .map(|arg| arg.arg_name.to_string())
94 .collect();
95 FunctionHelperVirtual {
96 function_name,
97 generated_args,
98 generated_function_body,
99 generated_virtual_function_signature,
100 return_type: function.return_type.clone(),
101 arg_names,
102 class_name: class_name.to_owned(),
103 }
104 }
105
106 pub fn generate_virtual_declaration(self) -> String {
110 let FunctionHelperVirtual {
111 function_name,
112 generated_args: _,
113 generated_function_body: _,
114 generated_virtual_function_signature,
115 return_type,
116 ..
117 } = self;
118 let function_name = function_name.to_case(Case::Camel);
119 let return_type_string = if let Some(wrapper) = return_type {
120 wrapper.get_name_for_abstract_method()
121 } else {
122 "Void".to_owned()
123 };
124 format!(" func {function_name}({generated_virtual_function_signature}) -> {return_type_string}\n")
125 }
126
127 pub fn generate_virtual_definition(self) -> String {
132 let FunctionHelperVirtual {
133 function_name,
134 generated_args,
135 generated_function_body,
136 generated_virtual_function_signature: _,
137 return_type,
138 arg_names: _,
139 class_name,
140 } = self;
141 let class_function_name = format!("{class_name}$");
142 let ffi_function_name =
143 format!("{EXPORTED_SYMBOLS_PREFIX}${class_function_name}{function_name}");
144 let generated_function_body = generated_function_body.join(", ");
145 let function_name = function_name.to_case(Case::Camel);
146 match return_type {
147 Some(WrapperType {
148 rust_type: RustWrapperType::Primitive | RustWrapperType::FieldlessEnum,
149 wrapper_name,
150 ..
151 }) =>
152 format!(
153 "@_cdecl(\"{ffi_function_name}\") func {ffi_function_name}({generated_args}) -> {wrapper_name} {{
154 return (_self as! {class_name}).{function_name}({generated_function_body})\n}}\n"),
155 None => format!(
156 "@_cdecl(\"{ffi_function_name}\") func {ffi_function_name}({generated_args}) {{
157 (_self as! {class_name}).{function_name}({generated_function_body})\n}}\n"),
158 _ =>
159 format!(
160 "@_cdecl(\"{ffi_function_name}\") func {ffi_function_name}({generated_args}) -> UnsafeMutableRawPointer {{
161 return convertToOwnedType((_self as! {class_name}).{function_name}({generated_function_body}))\n}}\n"),
162 }
163 }
164}
165
166pub struct FunctionTranslator {
171 pub function_name: String,
172 pub generated_args: String,
173 pub generated_function_body: Vec<String>,
174 pub return_type: Option<WrapperType>,
175 class_name: Option<String>,
176}
177
178impl FunctionTranslator {
179 pub fn from_class_method(function: &Function, class_name: &str) -> Self {
182 FunctionTranslator::from_function(function, Some(class_name.to_owned()))
183 }
184
185 pub fn from_global_function(function: &Function) -> Self {
188 FunctionTranslator::from_function(function, None)
189 }
190
191 fn from_function(function: &Function, class_name: Option<String>) -> Self {
195 let generated_args: String = function
196 .arguments
197 .iter()
198 .skip(class_name.is_some() as usize)
199 .map(|arg| {
200 let arg_name = &arg.arg_name;
201 let return_type_string = arg.typ.get_name();
202 format!("_ {arg_name}: {return_type_string}")
203 })
204 .collect::<Vec<String>>()
205 .join(", ");
206 let generated_function_body: Vec<String> = function
207 .arguments
208 .iter()
209 .skip(class_name.is_some() as usize)
210 .map(map_function_argument)
211 .collect();
212 let function_name = function.name.to_string();
213 FunctionTranslator {
214 function_name,
215 generated_args,
216 generated_function_body,
217 return_type: function.return_type.clone(),
218 class_name,
219 }
220 }
221
222 fn primitive_exception_throw(enum_name: impl Display, exception: impl Display) -> String {
223 let variant_check = format!(" == {enum_name}_{exception}");
224 format!(
225 "
226 else if (result.unwrapErr(){variant_check}) {{
227 throw {enum_name}_{exception}Exception(result.unwrapErr())
228 }}"
229 )
230 }
231
232 fn non_primitive_exception_throw(enum_name: impl Display, exception: impl Display) -> String {
233 let variant_check = format!(" == {enum_name}Tag_{exception}");
234 format!(
235 "
236 else if (result.unwrapErr().getTag(){variant_check}) {{
237 throw {enum_name}_{exception}Exception(result.unwrapErr())
238 }}"
239 )
240 }
241
242 pub fn generate_definition(self) -> String {
245 let FunctionTranslator {
246 function_name,
247 generated_args,
248 mut generated_function_body,
249 return_type,
250 class_name,
251 } = self;
252
253 let class_function_name = if let Some(class_name) = &class_name {
254 format!("{class_name}$")
255 } else {
256 "".to_owned()
257 };
258 let ffi_function_name =
259 format!("{EXPORTED_SYMBOLS_PREFIX}${class_function_name}{function_name}");
260 let function_name = function_name.to_case(Case::Camel);
261 if class_name.is_some() {
262 generated_function_body.insert(0, "self._self".to_owned());
263 }
264 let generated_function_body = generated_function_body.join(", ");
265 if let Some(ref wrapper) = return_type {
266 if let Some(WrapperType {
267 wrapper_name,
268 rust_type: RustWrapperType::Result(_, err_type),
269 ..
270 }) = &return_type
271 {
272 let exception_enum_name = &err_type.wrapper_name;
273 let exceptions_throws = match &err_type.rust_type {
274 RustWrapperType::Exceptions(Exceptions::Primitive(idents)) => idents
275 .iter()
276 .map(|exception| {
277 Self::primitive_exception_throw(exception_enum_name, exception)
278 })
279 .collect::<String>(),
280 RustWrapperType::Exceptions(Exceptions::NonPrimitive(idents)) => idents
281 .iter()
282 .map(|exception| {
283 Self::non_primitive_exception_throw(exception_enum_name, exception)
284 })
285 .collect::<String>(),
286 _ => panic!("Invalid wrapper type for exceptions wrapper"),
287 };
288 let return_type_string = wrapper.get_name();
289
290 format!("public func {function_name}({generated_args}) throws -> {return_type_string} {{
291 let result = {wrapper_name}({ffi_function_name}({generated_function_body}))
292 if (result.isOk()) {{
293 return result.unwrap()
294 }} {exceptions_throws}
295 else {{
296 fatalError(\"Unknown to ffi layer exception has been thrown\")
297 }}
298}}\n"
299 )
300 } else {
301 let return_type_string = wrapper.get_name();
302 format!(
303 " public func {function_name}({generated_args}) -> {return_type_string} {{
304 return {return_type_string}({ffi_function_name}({generated_function_body}))
305 }}\n"
306 )
307 }
308 } else {
309 format!(
310 " public func {function_name}({generated_args}) {{
311 {ffi_function_name}({generated_function_body})
312 }}\n"
313 )
314 }
315 }
316}
317
318fn map_function_argument(arg: &Arg) -> String {
319 if arg.typ.reference_parameters.is_some()
320 && arg.typ.rust_type != RustWrapperType::Primitive
321 && arg.typ.rust_type != RustWrapperType::FieldlessEnum
322 && arg.typ.rust_type != RustWrapperType::Trait
323 {
324 format!("{}.asRef()", arg.arg_name)
325 } else {
326 format!("convertToOwnedType({})", arg.arg_name.to_owned())
327 }
328}