{%- 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) %} 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) %} 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) %} 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) %} {%- let variant_name = variant|error_variant_name %} class {{ variant_name }}( {% for field in variant.fields() -%} {%- call kt::docstring(field, 8) %} val {% call kt::field_name(field, loop.index) %}: {{ 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) %}=${ {% call kt::field_name(field, loop.index) %} }{% if !loop.last %}, {% endif %}{% endfor %}" } {% endfor %} {% for meth in e.methods() -%} {%- call kt::func_decl("", meth, 8) %} {% endfor %} {%- call kt::uniffi_trait_impls(uniffi_trait_methods) %} 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) %} {% 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) %}) {%- 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) %}, buf) {%- endfor %} Unit } {%- endfor %} }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } } }