@@ -54,7 +54,7 @@ impl Default for StructBuilder {
5454 Self {
5555 source_module : syn:: parse_str ( "crate" ) . unwrap ( ) ,
5656 zresult : syn:: parse_str ( "ZResult" ) . unwrap ( ) ,
57- types : JniTypeBinding :: new ( ) ,
57+ types : JniTypeBinding :: new ( ) . with_builtins ( ) ,
5858 }
5959 }
6060}
@@ -180,53 +180,42 @@ impl JniStructConverter {
180180 let kotlin_fname = snake_to_camel ( & fname) ;
181181 let err_prefix = format ! ( "{struct_name}.{kotlin_fname}: {{}}" ) ;
182182
183- let kind = self . classify_struct_field ( & field. ty ) ;
184- match kind {
185- StructFieldKind :: Bool => {
186- field_preludes. push ( quote ! {
187- let #fname_ident = env. get_field( obj, #kotlin_fname, "Z" )
188- . and_then( |v| v. z( ) )
189- . map_err( |err| zerror!( #err_prefix, err) ) ?;
190- } ) ;
191- field_init. push ( quote ! { #fname_ident } ) ;
192- kotlin_field_lines. push ( format ! ( " val {}: Boolean," , kotlin_fname) ) ;
193- }
194- StructFieldKind :: I64 => {
195- field_preludes. push ( quote ! {
196- let #fname_ident = env. get_field( obj, #kotlin_fname, "J" )
197- . and_then( |v| v. j( ) )
198- . map_err( |err| zerror!( #err_prefix, err) ) ?;
199- } ) ;
200- field_init. push ( quote ! { #fname_ident } ) ;
201- kotlin_field_lines. push ( format ! ( " val {}: Long," , kotlin_fname) ) ;
202- }
203- StructFieldKind :: F64 => {
204- field_preludes. push ( quote ! {
205- let #fname_ident = env. get_field( obj, #kotlin_fname, "D" )
206- . and_then( |v| v. d( ) )
207- . map_err( |err| zerror!( #err_prefix, err) ) ?;
208- } ) ;
209- field_init. push ( quote ! { #fname_ident } ) ;
210- kotlin_field_lines. push ( format ! ( " val {}: Double," , kotlin_fname) ) ;
211- }
212- StructFieldKind :: Enum ( decoder) => {
213- let raw_ident = format_ident ! ( "__{}_raw" , fname_ident) ;
214- field_preludes. push ( quote ! {
215- let #raw_ident = env. get_field( obj, #kotlin_fname, "I" )
216- . and_then( |v| v. i( ) )
217- . map_err( |err| zerror!( #err_prefix, err) ) ?;
218- let #fname_ident = #decoder( #raw_ident) ?;
219- } ) ;
220- field_init. push ( quote ! { #fname_ident } ) ;
221- kotlin_field_lines. push ( format ! ( " val {}: Int," , kotlin_fname) ) ;
222- }
223- StructFieldKind :: Unsupported => panic ! (
183+ let binding = self . lookup_struct_field_binding ( & field. ty ) . unwrap_or_else ( || {
184+ panic ! (
224185 "unsupported field type `{}` for `{}.{}` at {loc}" ,
225186 field. ty. to_token_stream( ) ,
226187 struct_name,
227188 fname
228- ) ,
229- }
189+ )
190+ } ) ;
191+ let ( jni_sig, jvalue_method) =
192+ jni_primitive_signature ( binding. jni_type ( ) ) . unwrap_or_else ( || {
193+ panic ! (
194+ "field `{}.{}` at {loc}: type `{}` has non-primitive JNI wire form `{}`" ,
195+ struct_name,
196+ fname,
197+ field. ty. to_token_stream( ) ,
198+ binding. jni_type( ) . to_token_stream( )
199+ )
200+ } ) ;
201+ let raw_ident = format_ident ! ( "__{}_raw" , fname_ident) ;
202+ let jni_type = binding. jni_type ( ) ;
203+ let decode_expr = binding
204+ . decode ( )
205+ . expect ( "struct-field binding must have a decode" )
206+ . call ( & raw_ident) ;
207+ field_preludes. push ( quote ! {
208+ let #raw_ident: #jni_type = env. get_field( obj, #kotlin_fname, #jni_sig)
209+ . and_then( |v| v. #jvalue_method( ) )
210+ . map_err( |err| zerror!( #err_prefix, err) ) ? as _;
211+ let #fname_ident = #decode_expr;
212+ } ) ;
213+ field_init. push ( quote ! { #fname_ident } ) ;
214+ kotlin_field_lines. push ( format ! (
215+ " val {}: {}," ,
216+ kotlin_fname,
217+ binding. kotlin_type( )
218+ ) ) ;
230219 }
231220
232221 let tokens = quote ! {
@@ -261,28 +250,15 @@ impl JniStructConverter {
261250 syn:: parse2 ( tokens) . expect ( "generated struct decoder must parse" )
262251 }
263252
264- /// Classify a `#[prebindgen]` struct field's type for JNI round-tripping.
265- fn classify_struct_field ( & self , ty : & syn:: Type ) -> StructFieldKind {
266- let syn:: Type :: Path ( tp) = ty else {
267- return StructFieldKind :: Unsupported ;
268- } ;
269- let Some ( last) = tp. path . segments . last ( ) else {
270- return StructFieldKind :: Unsupported ;
271- } ;
253+ /// Look up a `#[prebindgen]` struct field's type in the registry. Fields
254+ /// must use the type's bare path-tail name (e.g. `bool`, `i64`,
255+ /// `CongestionControl`) and must resolve to a registered binding whose
256+ /// JNI wire form is one of the primitive `j*` types.
257+ fn lookup_struct_field_binding ( & self , ty : & syn:: Type ) -> Option < & TypeBinding > {
258+ let syn:: Type :: Path ( tp) = ty else { return None } ;
259+ let last = tp. path . segments . last ( ) ?;
272260 let name = last. ident . to_string ( ) ;
273- match name. as_str ( ) {
274- "bool" => StructFieldKind :: Bool ,
275- "i64" => StructFieldKind :: I64 ,
276- "f64" => StructFieldKind :: F64 ,
277- _ => {
278- if let Some ( binding) = self . cfg . types . types . get ( & name) {
279- if let Some ( p) = binding. enum_field_decoder_path ( ) {
280- return StructFieldKind :: Enum ( p. clone ( ) ) ;
281- }
282- }
283- StructFieldKind :: Unsupported
284- }
285- }
261+ self . cfg . types . types . get ( & name)
286262 }
287263}
288264
@@ -800,13 +776,26 @@ impl JniMethodsConverter {
800776// Internal helpers
801777// =====================================================================
802778
803- /// Field-type classification for `#[prebindgen]` struct fields.
804- enum StructFieldKind {
805- Bool ,
806- I64 ,
807- F64 ,
808- Enum ( syn:: Path ) ,
809- Unsupported ,
779+ /// Map a primitive JNI wire type (`jni::sys::j*`) to the JVM field
780+ /// signature character and the matching `JValue` accessor method.
781+ /// Returns `None` for non-primitive (object-shaped) wire types.
782+ fn jni_primitive_signature ( jni_type : & syn:: Type ) -> Option < ( & ' static str , syn:: Ident ) > {
783+ let syn:: Type :: Path ( tp) = jni_type else {
784+ return None ;
785+ } ;
786+ let last = tp. path . segments . last ( ) ?;
787+ let ( sig, accessor) = match last. ident . to_string ( ) . as_str ( ) {
788+ "jboolean" => ( "Z" , "z" ) ,
789+ "jbyte" => ( "B" , "b" ) ,
790+ "jchar" => ( "C" , "c" ) ,
791+ "jshort" => ( "S" , "s" ) ,
792+ "jint" => ( "I" , "i" ) ,
793+ "jlong" => ( "J" , "j" ) ,
794+ "jfloat" => ( "F" , "f" ) ,
795+ "jdouble" => ( "D" , "d" ) ,
796+ _ => return None ,
797+ } ;
798+ Some ( ( sig, format_ident ! ( "{}" , accessor) ) )
810799}
811800
812801fn is_unit ( ty : & syn:: Type ) -> bool {
0 commit comments