uniffi_bindgen 0.32.0

a multi-language bindings generator for rust (codegen and cli tooling)
Documentation
{%- let type_name = type_|type_name(ci) %}
{%- let ffi_converter_name = type_|ffi_converter_name %}
{%- let canonical_type_name = type_|canonical_name %}

{% if e.is_flat() %}
{%- call kt::docstring(e, 0) %}{% endcall %}
sealed class {{ type_name }}(message: String): kotlin.Exception(message){% if contains_object_references %}, Disposable {% endif %}
{%- let uniffi_trait_methods = e.uniffi_trait_methods() -%}
{%- if uniffi_trait_methods.ord_cmp.is_some() -%}
{% if contains_object_references %}, {% else %}, {% endif %}Comparable<{{ type_name }}>
{%- endif %} {
        {% for variant in e.variants() -%}
        {%- call kt::docstring(variant, 4) %}{% endcall %}
        class {{ variant|error_variant_name }}(message: String) : {{ type_name }}(message)
        {% endfor %}

    companion object ErrorHandler : UniffiRustCallStatusErrorHandler<{{ type_name }}> {
        override fun lift(error_buf: RustBuffer.ByValue): {{ type_name }} = {{ ffi_converter_name }}.lift(error_buf)
    }
}
{%- else %}
{%- call kt::docstring(e, 0) %}{% endcall %}
sealed class {{ type_name }}: kotlin.Exception(){% if contains_object_references %}, Disposable {% endif %}
{%- let uniffi_trait_methods = e.uniffi_trait_methods() -%}
{%- if uniffi_trait_methods.ord_cmp.is_some() -%}
{% if contains_object_references %}, {% else %}, {% endif %}Comparable<{{ type_name }}>
{%- endif %} {
    {% for variant in e.variants() -%}
    {%- call kt::docstring(variant, 4) %}{% endcall %}
    {%- let variant_name = variant|error_variant_name %}
    class {{ variant_name }}(
        {% for field in variant.fields() -%}
        {%- call kt::docstring(field, 8) %}{% endcall %}
        val {% call kt::field_name(field, loop.index) %}{% endcall %}: {{ field|type_name(ci) }}{% if loop.last %}{% else %}, {% endif %}
        {% endfor -%}
    ) : {{ type_name }}() {
        override val message
            get() = "{%- for field in variant.fields() %}{% call kt::field_name_unquoted(field, loop.index) %}{% endcall %}=${ {% call kt::field_name(field, loop.index) %}{% endcall %} }{% if !loop.last %}, {% endif %}{% endfor %}"
    }
    {% endfor %}

    {% for meth in e.methods() -%}
    {%- call kt::func_decl("", meth, 8) %}{% endcall %}
    {% endfor %}

    {%- call kt::uniffi_trait_impls(uniffi_trait_methods) %}{% endcall %}

    companion object ErrorHandler : UniffiRustCallStatusErrorHandler<{{ type_name }}> {
        override fun lift(error_buf: RustBuffer.ByValue): {{ type_name }} = {{ ffi_converter_name }}.lift(error_buf)
    }

    {% if contains_object_references %}
    @Suppress("UNNECESSARY_SAFE_CALL") // codegen is much simpler if we unconditionally emit safe calls here
    override fun destroy() {
        when(this) {
            {%- for variant in e.variants() %}
            is {{ type_name }}.{{ variant|error_variant_name }} -> {
                {%- if variant.has_fields() %}
                {% call kt::destroy_fields(variant) %}{% endcall %}
                {% else -%}
                // Nothing to destroy
                {%- endif %}
            }
            {%- endfor %}
        }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ }
    }
    {% endif %}
}
{%- endif %}

/**
 * @suppress
 */
public object {{ e|ffi_converter_name }} : FfiConverterRustBuffer<{{ type_name }}> {
    override fun read(buf: ByteBuffer): {{ type_name }} {
        {% if e.is_flat() %}
            return when(buf.getInt()) {
            {%- for variant in e.variants() %}
            {{ loop.index }} -> {{ type_name }}.{{ variant|error_variant_name }}({{ Type::String.borrow()|read_fn }}(buf))
            {%- endfor %}
            else -> throw RuntimeException("invalid error enum value, something is very wrong!!")
        }
        {% else %}

        return when(buf.getInt()) {
            {%- for variant in e.variants() %}
            {{ loop.index }} -> {{ type_name }}.{{ variant|error_variant_name }}({% if variant.has_fields() %}
                {% for field in variant.fields() -%}
                {{ field|read_fn }}(buf),
                {% endfor -%}
            {%- endif -%})
            {%- endfor %}
            else -> throw RuntimeException("invalid error enum value, something is very wrong!!")
        }
        {%- endif %}
    }

    override fun allocationSize(value: {{ type_name }}): ULong {
        {%- if e.is_flat() %}
        return 4UL
        {%- else %}
        return when(value) {
            {%- for variant in e.variants() %}
            is {{ type_name }}.{{ variant|error_variant_name }} -> (
                // Add the size for the Int that specifies the variant plus the size needed for all fields
                4UL
                {%- for field in variant.fields() %}
                + {{ field|allocation_size_fn }}(value.{% call kt::field_name(field, loop.index) %}{% endcall %})
                {%- endfor %}
            )
            {%- endfor %}
        }
        {%- endif %}
    }

    override fun write(value: {{ type_name }}, buf: ByteBuffer) {
        when(value) {
            {%- for variant in e.variants() %}
            is {{ type_name }}.{{ variant|error_variant_name }} -> {
                buf.putInt({{ loop.index }})
                {%- for field in variant.fields() %}
                {{ field|write_fn }}(value.{% call kt::field_name(field, loop.index) %}{% endcall %}, buf)
                {%- endfor %}
                Unit
            }
            {%- endfor %}
        }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ }
    }

}