summaryrefslogtreecommitdiffstats
path: root/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/macros.swift
blob: 8692cd6ff0712d092ed512d46bace96b532cb7f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
{#
// Template to call into rust. Used in several places.
// Variable names in `arg_list_decl` should match up with arg lists
// passed to rust via `arg_list_lowered`
#}

{%- macro to_ffi_call(func) -%}
    {%- call try(func) -%}
    {%- match func.throws_type() -%}
    {%- when Some with (e) -%}
        rustCallWithError({{ e|ffi_error_converter_name }}.lift) {
    {%- else -%}
        rustCall() {
    {%- endmatch %}
    {{ func.ffi_func().name() }}(
        {%- if func.takes_self() %}self.uniffiClonePointer(),{% endif %}
        {%- call arg_list_lowered(func) -%} $0
    )
}
{%- endmacro -%}

// eg, `public func foo_bar() { body }`
{%- macro func_decl(func_decl, callable, indent) %}
{%- call docstring(callable, indent) %}
{{ func_decl }} {{ callable.name()|fn_name }}(
    {%- call arg_list_decl(callable) -%})
    {%- call async(callable) %}
    {%- call throws(callable) %}
    {%- match callable.return_type() %}
    {%-  when Some with (return_type) %} -> {{ return_type|type_name }}
    {%-  when None %}
    {%- endmatch %} {
    {%- call call_body(callable) %}
}
{%- endmacro %}

// primary ctor - no name, no return-type.
{%- macro ctor_decl(callable, indent) %}
{%- call docstring(callable, indent) %}
public convenience init(
    {%- call arg_list_decl(callable) -%}) {%- call async(callable) %} {%- call throws(callable) %} {
    {%- if callable.is_async() %}
    let pointer =
        {%- call call_async(callable) %}
        {# The async mechanism returns an already constructed self.
           We work around that by cloning the pointer from that object, then
           assune the old object dies as there are no other references possible.
        #}
        .uniffiClonePointer()
    {%- else %}
    let pointer =
        {% call to_ffi_call(callable) %}
    {%- endif %}
    self.init(unsafeFromRawPointer: pointer)
}
{%- endmacro %}

{%- macro call_body(callable) %}
{%- if callable.is_async() %}
    return {%- call call_async(callable) %}
{%- else %}
{%-     match callable.return_type() -%}
{%-         when Some with (return_type) %}
    return {% call try(callable) %} {{ return_type|lift_fn }}({% call to_ffi_call(callable) %})
{%-         when None %}
{%-             call to_ffi_call(callable) %}
{%-     endmatch %}
{%- endif %}

{%- endmacro %}

{%- macro call_async(callable) %}
        {% call try(callable) %} await uniffiRustCallAsync(
            rustFutureFunc: {
                {{ callable.ffi_func().name() }}(
                    {%- if callable.takes_self() %}
                    self.uniffiClonePointer(){% if !callable.arguments().is_empty() %},{% endif %}
                    {% endif %}
                    {%- for arg in callable.arguments() -%}
                    {{ arg|lower_fn }}({{ arg.name()|var_name }}){% if !loop.last %},{% endif %}
                    {%- endfor %}
                )
            },
            pollFunc: {{ callable.ffi_rust_future_poll(ci) }},
            completeFunc: {{ callable.ffi_rust_future_complete(ci) }},
            freeFunc: {{ callable.ffi_rust_future_free(ci) }},
            {%- match callable.return_type() %}
            {%- when Some(return_type) %}
            liftFunc: {{ return_type|lift_fn }},
            {%- when None %}
            liftFunc: { $0 },
            {%- endmatch %}
            {%- match callable.throws_type() %}
            {%- when Some with (e) %}
            errorHandler: {{ e|ffi_error_converter_name }}.lift
            {%- else %}
            errorHandler: nil
            {% endmatch %}
        )
{%- endmacro %}

{%- macro arg_list_lowered(func) %}
    {%- for arg in func.arguments() %}
        {{ arg|lower_fn }}({{ arg.name()|var_name }}),
    {%- endfor %}
{%- endmacro -%}

{#-
// Arglist as used in Swift declarations of methods, functions and constructors.
// Note the var_name and type_name filters.
-#}

{% macro arg_list_decl(func) %}
    {%- for arg in func.arguments() -%}
        {% if config.omit_argument_labels() %}_ {% endif %}{{ arg.name()|var_name }}: {{ arg|type_name -}}
        {%- match arg.default_value() %}
        {%- when Some with(literal) %} = {{ literal|literal_swift(arg) }}
        {%- else %}
        {%- endmatch %}
        {%- if !loop.last %}, {% endif -%}
    {%- endfor %}
{%- endmacro %}

{#-
// Field lists as used in Swift declarations of Records and Enums.
// Note the var_name and type_name filters.
-#}
{% macro field_list_decl(item, has_nameless_fields) %}
    {%- for field in item.fields() -%}
        {%- call docstring(field, 8) %}
        {%- if has_nameless_fields %}
        {{- field|type_name -}}
        {%- if !loop.last -%}, {%- endif -%}
        {%- else -%}
        {{ field.name()|var_name }}: {{ field|type_name -}}
        {%- match field.default_value() %}
            {%- when Some with(literal) %} = {{ literal|literal_swift(field) }}
            {%- else %}
        {%- endmatch -%}
        {% if !loop.last %}, {% endif %}
        {%- endif -%}
    {%- endfor %}
{%- endmacro %}

{% macro field_name(field, field_num) %}
{%- if field.name().is_empty() -%}
v{{- field_num -}}
{%- else -%}
{{ field.name()|var_name }}
{%- endif -%}
{%- endmacro %}

{% macro arg_list_protocol(func) %}
    {%- for arg in func.arguments() -%}
        {% if config.omit_argument_labels() %}_ {% endif %}{{ arg.name()|var_name }}: {{ arg|type_name -}}
        {%- if !loop.last %}, {% endif -%}
    {%- endfor %}
{%- endmacro %}

{%- macro async(func) %}
{%- if func.is_async() %}async {% endif %}
{%- endmacro -%}

{%- macro throws(func) %}
{%- if func.throws() %}throws {% endif %}
{%- endmacro -%}

{%- macro try(func) %}
{%- if func.throws() %}try {% else %}try! {% endif %}
{%- endmacro -%}

{%- macro docstring_value(maybe_docstring, indent_spaces) %}
{%- match maybe_docstring %}
{%- when Some(docstring) %}
{{ docstring|docstring(indent_spaces) }}
{%- else %}
{%- endmatch %}
{%- endmacro %}

{%- macro docstring(defn, indent_spaces) %}
{%- call docstring_value(defn.docstring(), indent_spaces) %}
{%- endmacro %}