fn emit_trait_bridge_jni_external_funs(
out: &mut String,
config: &ResolvedCrateConfig,
exception_class: &str,
kotlin_package: &str,
emitted_native_names: &std::collections::HashSet<String>,
) {
let bridges: Vec<_> = config
.trait_bridges
.iter()
.filter(|b| !b.exclude_languages.iter().any(|l| l == "kotlin_android"))
.collect();
if bridges.is_empty() {
return;
}
out.push_str("\n // JNI trait-bridge external funs — implementations are Rust JNI shims.\n");
for bridge in &bridges {
let trait_pascal = to_pascal_case(&bridge.trait_name);
let iface_fqn = format!("{kotlin_package}.I{trait_pascal}");
if bridge.register_fn.is_some() {
let native_name = format!("nativeRegister{trait_pascal}");
if !emitted_native_names.contains(&native_name) {
out.push('\n');
push_jni_external_fun(
out,
&native_name,
&format!("impl: {iface_fqn}"),
None,
Some(exception_class),
);
}
}
if bridge.unregister_fn.is_some() {
let native_name = format!("nativeUnregister{trait_pascal}");
if !emitted_native_names.contains(&native_name) {
push_jni_external_fun(out, &native_name, "name: String", None, Some(exception_class));
}
}
if bridge.clear_fn.is_some() {
let native_name = format!("nativeClear{trait_pascal}s");
if !emitted_native_names.contains(&native_name) {
push_jni_external_fun(out, &native_name, "", None, Some(exception_class));
}
}
}
}