use std::fmt::Display;
use super::{function_helper::*, templates::*, translate_c_enums};
use crate::binding_types::{Exceptions, RustWrapperType, WrapperType};
use crate::cpp::externs::create_extern_imports;
use crate::cpp::generator::create_classes_forward_declarations;
use crate::enum_helpers::{
create_field_getter_function,
create_variant_getter_function,
enum_tag_name,
get_fields,
is_many_fields_variant,
is_primitive_enum,
variant_wrapper_ident,
};
use crate::extern_module_translator::{ExternFunction, ExternModuleTranslator, Function};
use crate::EXPORTED_SYMBOLS_PREFIX;
fn create_class_methods_definitions(extern_module_translator: &ExternModuleTranslator) -> String {
extern_module_translator
.user_custom_types
.iter()
.map(|(wrapper_type, vec_of_functions)| {
let class_name = wrapper_type.wrapper_name.to_string();
let class_functions = vec_of_functions
.iter()
.map(|f| FunctionTranslator::from_class_method(f, &class_name))
.map(FunctionTranslator::generate_definition)
.collect::<String>();
custom_class_definition(&class_name, &class_functions)
})
.collect::<String>()
}
fn translate_type_names(mut fun: Function) -> Function {
if let Some(ret_type) = &mut fun.return_type {
if ret_type.wrapper_name.as_str() == "String" {
ret_type.wrapper_name = "RustString".to_string()
}
}
fun
}
fn create_complex_enum_wrappers(extern_module_translator: &ExternModuleTranslator) -> String {
extern_module_translator
.shared_enums
.iter()
.filter(|e| !is_primitive_enum(e))
.map(|enum_item| {
let class_name = enum_item.ident.to_string();
let variant_getters = enum_item
.variants
.iter()
.filter_map(|variant| create_variant_getter_function(enum_item, variant))
.map(translate_type_names);
let many_fields_variants_wrapper: String = enum_item
.variants
.iter()
.filter(|v| is_many_fields_variant(v))
.map(|variant| {
let fields = get_fields(variant).unwrap();
let variant_wrapper_name =
variant_wrapper_ident(&enum_item.ident, &variant.ident).to_string();
let variant_wrapper_getters = fields
.iter()
.enumerate()
.map(|(field_idx, field)| {
translate_type_names(create_field_getter_function(
enum_item, variant, field, field_idx,
))
})
.map(|f| FunctionTranslator::from_class_method(&f, &variant_wrapper_name))
.map(FunctionTranslator::generate_definition)
.collect::<String>();
custom_class_definition(variant_wrapper_name.as_str(), &variant_wrapper_getters)
})
.collect();
let class_functions = variant_getters
.map(|f| FunctionTranslator::from_class_method(&f, &class_name))
.map(FunctionTranslator::generate_definition)
.collect::<String>();
let enum_tag_name = enum_tag_name(&enum_item.ident);
let tag_getter_fn = format!(
" public func getTag() -> {enum_tag_name} {{
return self._self.load(as: {enum_tag_name}.self)
}}\n"
);
custom_class_definition(&class_name, &(class_functions + &tag_getter_fn))
+ &many_fields_variants_wrapper
})
.collect::<String>()
}
fn create_abstract_classes_declarations(
extern_module_translator: &ExternModuleTranslator,
) -> String {
extern_module_translator
.user_traits
.iter()
.map(|(wrapper_type, vec_of_functions)| {
let class_name = wrapper_type.wrapper_name.to_string();
let functions_declaration: String = vec_of_functions
.iter()
.map(|f| FunctionHelperVirtual::from_virtual_function(f, &class_name))
.map(FunctionHelperVirtual::generate_virtual_declaration)
.collect();
abstract_class_declaration(&class_name, &functions_declaration)
})
.collect::<String>()
}
fn create_virtual_method_calls(extern_module_translator: &ExternModuleTranslator) -> String {
extern_module_translator
.user_traits
.iter()
.map(|(wrapper_type, vec_of_functions)| {
let class_name = wrapper_type.wrapper_name.to_string();
vec_of_functions
.iter()
.map(|f| FunctionHelperVirtual::from_virtual_function(f, &class_name))
.map(FunctionHelperVirtual::generate_virtual_definition)
.collect::<String>()
})
.collect::<String>()
}
fn create_rust_types_wrappers(extern_module_translator: &ExternModuleTranslator) -> String {
extern_module_translator
.rust_types_wrappers
.ordered_iter()
.filter_map(|wrapper| match wrapper {
WrapperType {
rust_type: RustWrapperType::Vector(inner_type),
..
} => {
let inner_type_name = inner_type.get_name();
let is_generic = matches!(inner_type.rust_type, RustWrapperType::Option(_))
|| matches!(inner_type.rust_type, RustWrapperType::Vector(_));
Some(vector_impl(
&inner_type_name,
&inner_type.wrapper_name,
is_generic,
))
}
WrapperType {
rust_type: RustWrapperType::Option(inner_type),
..
} => {
let inner_type_name = inner_type.get_name();
let is_generic = matches!(inner_type.rust_type, RustWrapperType::Option(_))
|| matches!(inner_type.rust_type, RustWrapperType::Vector(_));
Some(option_class(
&inner_type_name,
&inner_type.wrapper_name,
is_generic,
))
}
WrapperType {
rust_type: RustWrapperType::Exceptions(Exceptions::NonPrimitive(idents)),
wrapper_name,
..
} => Some(
idents
.iter()
.map(|exception| {
create_non_primitive_exception_class(
&exception.to_string(),
wrapper_name,
extern_module_translator.exception_trait_methods.iter(),
)
})
.collect::<String>(),
),
WrapperType {
rust_type: RustWrapperType::Exceptions(Exceptions::Primitive(idents)),
wrapper_name,
..
} => Some(
idents
.iter()
.map(|exception| {
create_primitive_exception_class(
&exception.to_string(),
wrapper_name,
extern_module_translator.exception_trait_methods.iter(),
)
})
.collect::<String>(),
),
_ => None,
})
.collect()
}
fn create_global_functions_definitions(
extern_module_translator: &ExternModuleTranslator,
) -> String {
extern_module_translator
.global_functions
.iter()
.map(FunctionTranslator::from_global_function)
.map(FunctionTranslator::generate_definition)
.collect()
}
pub fn create_non_primitive_exception_class<'a>(
exception: &impl Display,
err_name: &impl Display,
custom_methods: impl Iterator<Item = &'a Function>,
) -> String {
let custom_methods = create_exception_custom_methods(custom_methods, err_name, "err._self");
format_exception_class(exception, err_name, &custom_methods)
}
pub fn create_primitive_exception_class<'a>(
exception: &impl Display,
err_name: &impl Display,
custom_methods: impl Iterator<Item = &'a Function>,
) -> String {
let custom_methods = create_exception_custom_methods(custom_methods, err_name, "&err");
format_exception_class(exception, err_name, &custom_methods)
}
fn format_exception_class(
exception: &impl Display,
err_name: &impl Display,
custom_methods: &impl Display,
) -> String {
let exception_name = format!("{err_name}_{exception}Exception");
format!(
"
public class {exception_name} : {RUST_EXCEPTION_BASE_CLASS_NAME} {{
private(set) var err: {err_name}
init(_ err: {err_name}) {{ self.err = err }}
{custom_methods}
}}
"
)
}
fn create_enum_init_method(extern_module_translator: &ExternModuleTranslator) -> String {
extern_module_translator
.shared_enums
.iter()
.filter(|e| is_primitive_enum(e))
.map(|enum_class| {
let enum_name = &enum_class.ident;
format!(
"extension {enum_name} {{
init(_ enumObj: {enum_name}) {{
self = enumObj
}}
}}\n"
)
})
.collect()
}
fn create_result_wrappers(extern_module_translator: &ExternModuleTranslator) -> String {
extern_module_translator
.rust_types_wrappers
.ordered_iter()
.filter_map(|wrapper| match wrapper {
WrapperType {
rust_type: RustWrapperType::Result(ok_type, exceptions_type),
..
} => {
let ok_type = ok_type.get_name();
let error_enum_name = &exceptions_type.wrapper_name;
Some(result_class(
&wrapper.wrapper_name,
&ok_type,
error_enum_name,
))
}
_ => None,
})
.collect()
}
fn create_exception_custom_methods<'a>(
custom_methods: impl Iterator<Item = &'a Function>,
err_name: &impl Display,
rust_obj_ptr: impl Display,
) -> impl Display {
custom_methods
.map(|fun| {
let return_type = fun
.return_type
.as_ref()
.map(|wrapper| wrapper.wrapper_name.as_str())
.unwrap_or("");
let function_name = &fun.name;
let ffi_call = format!("{EXPORTED_SYMBOLS_PREFIX}${err_name}${function_name}");
let ffi_call = format!("{ffi_call}({rust_obj_ptr})");
let ffi_call = match &fun.return_type {
None
| Some(WrapperType {
rust_type: RustWrapperType::Primitive | RustWrapperType::FieldlessEnum,
..
}) => ffi_call,
Some(WrapperType { wrapper_name, .. }) => {
format!("{wrapper_name}({ffi_call})")
}
};
format!(
" public func {function_name}() -> {return_type} {{
return {ffi_call}
}}"
)
})
.collect::<Vec<_>>()
.join("\n")
}
fn base_exception_method(function: &Function) -> String {
let return_type = &function
.return_type
.as_ref()
.map(|t| t.get_name())
.unwrap_or_else(|| "".to_string());
let name = &function.name;
format!(" func {name}() -> {return_type};")
}
fn base_exception_class(emt: &ExternModuleTranslator) -> String {
let exception_trait_methods = emt
.exception_trait_methods
.iter()
.map(base_exception_method)
.collect::<Vec<_>>()
.join("\n");
format!("public protocol {RUST_EXCEPTION_BASE_CLASS_NAME} : Error {{\n{exception_trait_methods}\n}}\n")
}
pub fn generate_swift_file(extern_module_translator: &ExternModuleTranslator) -> String {
let classes_definition = create_class_methods_definitions(extern_module_translator);
let complex_enum_classes_definitions = create_complex_enum_wrappers(extern_module_translator);
let abstract_classes_declaration =
create_abstract_classes_declarations(extern_module_translator);
let virtual_methods_calls = create_virtual_method_calls(extern_module_translator);
let rust_types_wrappers = create_rust_types_wrappers(extern_module_translator);
let global_functions_definition: String =
create_global_functions_definitions(extern_module_translator);
let base_exception_class = base_exception_class(extern_module_translator);
let result_wrapper = create_result_wrappers(extern_module_translator);
let enum_init_methods = create_enum_init_method(extern_module_translator);
format!(
"{PREDEFINED}
{enum_init_methods}
{complex_enum_classes_definitions}
{result_wrapper}
{base_exception_class}
{rust_types_wrappers}
{classes_definition}
{global_functions_definition}
{virtual_methods_calls}
{abstract_classes_declaration}"
)
}
pub fn generate_c_externs_file(
extern_module_translator: &ExternModuleTranslator,
extern_functions: &[ExternFunction],
) -> String {
let externs = create_extern_imports(extern_functions);
let classes_forward_declarations =
create_classes_forward_declarations(extern_module_translator);
let enum_classes_definitions = translate_c_enums(extern_module_translator);
format!(
"#include <stdbool.h>
#include <stdint.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
typedef float f32;
typedef double f64;
typedef intptr_t isize;
typedef uintptr_t usize;
{enum_classes_definitions}
{classes_forward_declarations}
{externs}
"
)
}