Skip to content

Commit 6cb3fec

Browse files
committed
value type return fix
1 parent 5c03b5c commit 6cb3fec

1 file changed

Lines changed: 44 additions & 0 deletions

File tree

prebindgen-ext/src/jni/jni_ext.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4252,6 +4252,50 @@ fn struct_output_body(
42524252
format!("{}/{}", ext.java_class_prefix, struct_name)
42534253
};
42544254

4255+
// A `value_class` is JVM-erased to its single wrapped field, so its JObject
4256+
// form is that inner field's encoded value (e.g. `ZBytes`/`ZenohId` → a
4257+
// `[B` byte array), never a boxed wrapper object — Kotlin never
4258+
// materializes the wrapper. Boxing it via `new_object` would produce an
4259+
// object the consumer reinterprets as the erased inner type (e.g. a
4260+
// `ZBytes` stored into a `byte[]` slot → corrupt array). The data-class
4261+
// encoder already computes the erased inner descriptor for value-class
4262+
// fields, so emit the inner converter here to match. Only object-shaped
4263+
// inners can be returned as a bare JObject; primitive-backed value classes
4264+
// would need boxing and none exist today, so those fall through.
4265+
//
4266+
// The inner field is *moved* into the (by-value) inner converter — `v` is
4267+
// owned here and the single field is never read again. Moving (vs cloning)
4268+
// avoids a redundant copy of the payload and imposes no `Clone` bound on
4269+
// the inner type. A value class that implemented `Drop` would block the
4270+
// partial move with a clear compile error, but newtype wrappers don't.
4271+
if ext
4272+
.types
4273+
.get(&TypeKey::from_type(&struct_ty))
4274+
.map(|c| c.value_class)
4275+
.unwrap_or(false)
4276+
{
4277+
if let syn::Fields::Named(named) = &s.fields {
4278+
if let Some(inner) = named.named.first() {
4279+
if let (Some(inner_ident), Some(inner_entry)) =
4280+
(inner.ident.clone(), registry.output_entry(&inner.ty))
4281+
{
4282+
if matches!(
4283+
jni_field_access(&inner_entry.destination),
4284+
Some((_, _, true)) | None
4285+
) {
4286+
let inner_conv = inner_entry.function.sig.ident.clone();
4287+
let body: syn::Expr = syn::parse_quote!({
4288+
let __inner = #inner_conv(env, v.#inner_ident)?;
4289+
let __obj: jni::objects::JObject = __inner.into();
4290+
__obj
4291+
});
4292+
return Some((syn::parse_quote!(jni::objects::JObject), body));
4293+
}
4294+
}
4295+
}
4296+
}
4297+
}
4298+
42554299
let syn::Fields::Named(named) = &s.fields else {
42564300
return None;
42574301
};

0 commit comments

Comments
 (0)