summaryrefslogtreecommitdiffstats
path: root/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/ObjectTemplate.kt
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/ObjectTemplate.kt')
-rw-r--r--third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/ObjectTemplate.kt138
1 files changed, 138 insertions, 0 deletions
diff --git a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/ObjectTemplate.kt b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/ObjectTemplate.kt
new file mode 100644
index 0000000000..8ce27a5d04
--- /dev/null
+++ b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/ObjectTemplate.kt
@@ -0,0 +1,138 @@
+{%- let obj = ci|get_object_definition(name) %}
+{%- if self.include_once_check("ObjectRuntime.kt") %}{% include "ObjectRuntime.kt" %}{% endif %}
+{{- self.add_import("java.util.concurrent.atomic.AtomicLong") }}
+{{- self.add_import("java.util.concurrent.atomic.AtomicBoolean") }}
+
+public interface {{ type_name }}Interface {
+ {% for meth in obj.methods() -%}
+ {%- match meth.throws_type() -%}
+ {%- when Some with (throwable) -%}
+ @Throws({{ throwable|type_name(ci) }}::class)
+ {%- when None -%}
+ {%- endmatch %}
+ {% if meth.is_async() -%}
+ suspend fun {{ meth.name()|fn_name }}({% call kt::arg_list_decl(meth) %})
+ {%- else -%}
+ fun {{ meth.name()|fn_name }}({% call kt::arg_list_decl(meth) %})
+ {%- endif %}
+ {%- match meth.return_type() -%}
+ {%- when Some with (return_type) %}: {{ return_type|type_name(ci) -}}
+ {%- when None -%}
+ {%- endmatch -%}
+
+ {% endfor %}
+ companion object
+}
+
+class {{ type_name }}(
+ pointer: Pointer
+) : FFIObject(pointer), {{ type_name }}Interface {
+
+ {%- match obj.primary_constructor() %}
+ {%- when Some with (cons) %}
+ constructor({% call kt::arg_list_decl(cons) -%}) :
+ this({% call kt::to_ffi_call(cons) %})
+ {%- when None %}
+ {%- endmatch %}
+
+ /**
+ * Disconnect the object from the underlying Rust object.
+ *
+ * It can be called more than once, but once called, interacting with the object
+ * causes an `IllegalStateException`.
+ *
+ * Clients **must** call this method once done with the object, or cause a memory leak.
+ */
+ override protected fun freeRustArcPtr() {
+ rustCall() { status ->
+ _UniFFILib.INSTANCE.{{ obj.ffi_object_free().name() }}(this.pointer, status)
+ }
+ }
+
+ {% for meth in obj.methods() -%}
+ {%- match meth.throws_type() -%}
+ {%- when Some with (throwable) %}
+ @Throws({{ throwable|type_name(ci) }}::class)
+ {%- else -%}
+ {%- endmatch -%}
+ {%- if meth.is_async() %}
+ @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
+ override suspend fun {{ meth.name()|fn_name }}({%- call kt::arg_list_decl(meth) -%}){% match meth.return_type() %}{% when Some with (return_type) %} : {{ return_type|type_name(ci) }}{% when None %}{%- endmatch %} {
+ return uniffiRustCallAsync(
+ callWithPointer { thisPtr ->
+ _UniFFILib.INSTANCE.{{ meth.ffi_func().name() }}(
+ thisPtr,
+ {% call kt::arg_list_lowered(meth) %}
+ )
+ },
+ {{ meth|async_poll(ci) }},
+ {{ meth|async_complete(ci) }},
+ {{ meth|async_free(ci) }},
+ // lift function
+ {%- match meth.return_type() %}
+ {%- when Some(return_type) %}
+ { {{ return_type|lift_fn }}(it) },
+ {%- when None %}
+ { Unit },
+ {% endmatch %}
+ // Error FFI converter
+ {%- match meth.throws_type() %}
+ {%- when Some(e) %}
+ {{ e|type_name(ci) }}.ErrorHandler,
+ {%- when None %}
+ NullCallStatusErrorHandler,
+ {%- endmatch %}
+ )
+ }
+ {%- else -%}
+ {%- match meth.return_type() -%}
+ {%- when Some with (return_type) -%}
+ override fun {{ meth.name()|fn_name }}({% call kt::arg_list_protocol(meth) %}): {{ return_type|type_name(ci) }} =
+ callWithPointer {
+ {%- call kt::to_ffi_call_with_prefix("it", meth) %}
+ }.let {
+ {{ return_type|lift_fn }}(it)
+ }
+
+ {%- when None -%}
+ override fun {{ meth.name()|fn_name }}({% call kt::arg_list_protocol(meth) %}) =
+ callWithPointer {
+ {%- call kt::to_ffi_call_with_prefix("it", meth) %}
+ }
+ {% endmatch %}
+ {% endif %}
+ {% endfor %}
+
+ {% if !obj.alternate_constructors().is_empty() -%}
+ companion object {
+ {% for cons in obj.alternate_constructors() -%}
+ fun {{ cons.name()|fn_name }}({% call kt::arg_list_decl(cons) %}): {{ type_name }} =
+ {{ type_name }}({% call kt::to_ffi_call(cons) %})
+ {% endfor %}
+ }
+ {% else %}
+ companion object
+ {% endif %}
+}
+
+public object {{ obj|ffi_converter_name }}: FfiConverter<{{ type_name }}, Pointer> {
+ override fun lower(value: {{ type_name }}): Pointer = value.callWithPointer { it }
+
+ override fun lift(value: Pointer): {{ type_name }} {
+ return {{ type_name }}(value)
+ }
+
+ override fun read(buf: ByteBuffer): {{ type_name }} {
+ // The Rust code always writes pointers as 8 bytes, and will
+ // fail to compile if they don't fit.
+ return lift(Pointer(buf.getLong()))
+ }
+
+ override fun allocationSize(value: {{ type_name }}) = 8
+
+ override fun write(value: {{ type_name }}, buf: ByteBuffer) {
+ // The Rust code always expects pointers written as 8 bytes,
+ // and will fail to compile if they don't fit.
+ buf.putLong(Pointer.nativeValue(lower(value)))
+ }
+}