blob: fb272a18966296eebaebaa9f7d9e51512cf3ade1 [file] [log] [blame]
//* Copyright 2024 The Dawn & Tint Authors
//*
//* Redistribution and use in source and binary forms, with or without
//* modification, are permitted provided that the following conditions are met:
//*
//* 1. Redistributions of source code must retain the above copyright notice, this
//* list of conditions and the following disclaimer.
//*
//* 2. Redistributions in binary form must reproduce the above copyright notice,
//* this list of conditions and the following disclaimer in the documentation
//* and/or other materials provided with the distribution.
//*
//* 3. Neither the name of the copyright holder nor the names of its
//* contributors may be used to endorse or promote products derived from
//* this software without specific prior written permission.
//*
//* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
//* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
//* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
//* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
//* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
//* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{% macro arg_to_jni_type(arg) %}
{%- if arg == None -%}
void
{%- elif arg.length and arg.length != 'constant' -%}
{%- if arg.type.category in ['callback function', 'function pointer', 'kotlin type', 'object', 'structure'] -%}
jobjectArray
{%- elif arg.type.name.get() == 'void' -%}
jobject
{%- elif arg.type.category in ['bitmask', 'enum'] or arg.type.name.get() == 'uint32_t' -%}
jintArray
{%- else -%}
{{ unreachable_code() }}
{%- endif -%}
{%- else -%}
{{ to_jni_type(arg.type) }}
{%- endif -%}
{% endmacro %}
{% macro to_jni_type(type) %}
{%- if type.name.get() == "string view" -%}
jstring
{%- elif type.category in ['callback function', 'function pointer', 'kotlin type', 'object', 'structure'] -%}
jobject
{%- elif type.category in ['bitmask', 'enum'] -%}
jint
{%- else -%}
{{ jni_primitives[type.name.get()] }}
{%- endif -%}
{% endmacro %}
{% macro jni_signature(member) %}
{%- if member.type.name.get() == 'string view' -%}
Ljava/lang/String;
{%- elif member.length and member.length != 'constant' -%}
[{{ jni_signature_single_value(member.type) }}
{%- else -%}
{{ jni_signature_single_value(member.type) }}
{%- endif %}
{% endmacro %}
{% macro jni_signature_single_value(type) %}
{%- if type.category in ['callback function', 'function pointer', 'kotlin type', 'object', 'structure'] -%}
L{{ jni_name(type, type.category) }};
{%- elif type.category in ['bitmask', 'enum'] -%}
{{ jni_signatures['int32_t'] }}
{%- elif type.category == 'native' -%}
{{ jni_signatures[type.name.get()] }}
{%- else -%}
{{ unreachable_code('Unsupported type: ' + type.name.get()) }}
{%- endif -%}
{% endmacro %}
{% macro convert_to_kotlin(input, output, size, member) %}
{% if size is string %}
{% if member.type.name.get() in ['void const *', 'void *'] %}
jobject {{ output }} = toByteBuffer(env, {{ input }}, {{ size }});
{% elif member.type.category in ['object', 'structure'] %}
//* Native container converted to a Kotlin container.
jobjectArray {{ output }} = env->NewObjectArray(
{{ size }}, classes->{{ member.type.name.camelCase() }}, 0);
for (int idx = 0; idx != {{ size }}; idx++) {
{{ convert_to_kotlin(input + '[idx]', 'element', None, {'type': member.type}) | indent(4) }}
env->SetObjectArrayElement({{ output }}, idx, element);
}
{% elif member.type.category in ['bitmask', 'enum'] or member.type.name.get() in ['int', 'int32_t', 'uint32_t'] %}
jintArray {{ output }} = env->NewIntArray({{ size }});
{{' '}}env->SetIntArrayRegion({{ output }}, 0, {{ size }}, reinterpret_cast<const jint *>({{ input }}));
{% else %}
{{ unreachable_code() }}
{% endif %}
{% elif member.type.category == 'object' %}
jobject {{ output }};
{
jclass clz = classes->{{ member.type.name.camelCase() }};
jmethodID init = env->GetMethodID(clz, "<init>", "(J)V");
{{ output }} = env->NewObject(clz, init, reinterpret_cast<jlong>({{ input }}));
}
{% elif member.type.category == 'structure' %}
jobject {{ output }} = ToKotlin(env, {{ '&' if member.annotation not in ['*', 'const*'] }}{{ input }});
{% elif member.type.category in ['bitmask', 'enum', 'native'] %}
//* We use Kotlin value classes for bitmask and enum, and they get inlined as lone values.
{{ to_jni_type(member.type) }} {{ output }} = static_cast<{{ to_jni_type(member.type) }}>({{ input }});
{% elif member.type.category != 'kotlin type' %}
{{ unreachable_code('Unsupported type: ' + member.type.name.get()) }}
{% endif %}
{% endmacro %}