@@ -63,6 +63,7 @@ pub struct CParameter {
6363 pub transfer : library:: Transfer ,
6464 pub caller_allocates : bool ,
6565 pub is_error : bool ,
66+ pub has_length : bool ,
6667 pub scope : ParameterScope ,
6768 /// Index of the user data parameter associated with the callback.
6869 pub user_data_index : Option < usize > ,
@@ -76,6 +77,25 @@ pub struct CParameter {
7677 pub move_ : bool ,
7778}
7879
80+ impl CParameter {
81+ pub fn is_gstr ( & self , env : & Env ) -> bool {
82+ matches ! (
83+ env. type_( self . typ) ,
84+ library:: Type :: Basic ( library:: Basic :: Utf8 )
85+ ) && self . ref_mode . is_ref ( )
86+ }
87+ pub fn is_strv ( & self , env : & Env ) -> bool {
88+ if let library:: Type :: CArray ( inner) = env. type_ ( self . typ ) {
89+ matches ! (
90+ env. type_( * inner) ,
91+ library:: Type :: Basic ( library:: Basic :: Utf8 )
92+ ) && !matches ! ( self . c_type. as_str( ) , "char**" | "gchar**" )
93+ } else {
94+ false
95+ }
96+ }
97+ }
98+
7999#[ derive( Clone , Debug ) ]
80100pub enum TransformationType {
81101 ToGlibDirect {
@@ -288,7 +308,7 @@ pub fn analyze(
288308 array_par = array_lengths. get ( & ( pos as u32 ) ) . copied ( ) ;
289309 }
290310 if array_par. is_none ( ) && !disable_length_detect {
291- array_par = detect_length ( env, pos, par, function_parameters) ;
311+ array_par = detect_array ( env, pos, par, function_parameters) ;
292312 }
293313 if let Some ( array_par) = array_par {
294314 let mut array_name = nameutil:: mangle_keywords ( & array_par. name ) ;
@@ -319,6 +339,9 @@ pub fn analyze(
319339 } ;
320340 parameters. transformations . push ( transformation) ;
321341 }
342+ let has_length = par. array_length . is_some ( )
343+ || ( !disable_length_detect
344+ && detect_length ( env, pos, par, function_parameters) . is_some ( ) ) ;
322345
323346 let immutable = configured_parameters. iter ( ) . any ( |p| p. constant ) ;
324347 let ref_mode =
@@ -340,6 +363,7 @@ pub fn analyze(
340363 nullable,
341364 ref_mode,
342365 is_error : par. is_error ,
366+ has_length,
343367 scope : par. scope ,
344368 user_data_index : par. closure ,
345369 destroy_index : par. destroy ,
@@ -454,31 +478,22 @@ pub fn analyze(
454478 }
455479
456480 let c_par = parameters. c_parameters . last ( ) . unwrap ( ) ;
457- match env. type_ ( typ) {
458- library:: Type :: Basic ( library:: Basic :: Utf8 ) if ref_mode. is_ref ( ) => {
459- transformation. transformation_type = TransformationType :: RunWith {
460- name : c_par. name . clone ( ) ,
461- func : if * c_par. nullable {
462- nameutil:: use_glib_type ( env, "IntoOptionalGStr::run_with_gstr" )
463- } else {
464- nameutil:: use_glib_type ( env, "IntoGStr::run_with_gstr" )
465- } ,
466- inner : Box :: new ( transformation. transformation_type ) ,
467- } ;
468- }
469- library:: Type :: CArray ( inner)
470- if matches ! (
471- env. type_( * inner) ,
472- library:: Type :: Basic ( library:: Basic :: Utf8 )
473- ) && !matches ! ( c_par. c_type. as_str( ) , "char**" | "gchar**" ) =>
474- {
475- transformation. transformation_type = TransformationType :: RunWith {
476- name : c_par. name . clone ( ) ,
477- func : nameutil:: use_glib_type ( env, "IntoStrV::run_with_strv" ) ,
478- inner : Box :: new ( TransformationType :: AsPtr ( c_par. name . clone ( ) ) ) ,
479- } ;
480- }
481- _ => { }
481+ if c_par. is_gstr ( env) && !has_length {
482+ transformation. transformation_type = TransformationType :: RunWith {
483+ name : c_par. name . clone ( ) ,
484+ func : if * c_par. nullable {
485+ nameutil:: use_glib_type ( env, "IntoOptionalGStr::run_with_gstr" )
486+ } else {
487+ nameutil:: use_glib_type ( env, "IntoGStr::run_with_gstr" )
488+ } ,
489+ inner : Box :: new ( transformation. transformation_type ) ,
490+ } ;
491+ } else if c_par. is_strv ( env) {
492+ transformation. transformation_type = TransformationType :: RunWith {
493+ name : c_par. name . clone ( ) ,
494+ func : nameutil:: use_glib_type ( env, "IntoStrV::run_with_strv" ) ,
495+ inner : Box :: new ( TransformationType :: AsPtr ( c_par. name . clone ( ) ) ) ,
496+ } ;
482497 }
483498
484499 parameters. transformations . push ( transformation) ;
@@ -507,30 +522,33 @@ fn detect_length<'a>(
507522 par : & library:: Parameter ,
508523 parameters : & ' a [ library:: Parameter ] ,
509524) -> Option < & ' a library:: Parameter > {
510- if !is_length ( par) || pos == 0 {
525+ if !has_length ( env , par. typ ) {
511526 return None ;
512527 }
513528
514- parameters. get ( pos - 1 ) . and_then ( |p| {
515- if has_length ( env, p. typ ) {
516- Some ( p)
517- } else {
518- None
519- }
520- } )
529+ parameters
530+ . get ( pos + 1 )
531+ . and_then ( |p| is_length ( p) . then_some ( p) )
521532}
522533
523- fn is_length ( par : & library:: Parameter ) -> bool {
524- if par. direction != library:: ParameterDirection :: In {
525- return false ;
534+ fn detect_array < ' a > (
535+ env : & Env ,
536+ pos : usize ,
537+ par : & library:: Parameter ,
538+ parameters : & ' a [ library:: Parameter ] ,
539+ ) -> Option < & ' a library:: Parameter > {
540+ if pos == 0 || !is_length ( par) {
541+ return None ;
526542 }
527543
528- let len = par . name . len ( ) ;
529- if len >= 3 && & par . name [ len - 3 ..len ] == "len" {
530- return true ;
531- }
544+ parameters
545+ . get ( pos - 1 )
546+ . and_then ( |p| has_length ( env , p . typ ) . then_some ( p ) )
547+ }
532548
533- par. name . contains ( "length" )
549+ fn is_length ( par : & library:: Parameter ) -> bool {
550+ par. direction == library:: ParameterDirection :: In
551+ && ( par. name . ends_with ( "len" ) || par. name . contains ( "length" ) )
534552}
535553
536554fn has_length ( env : & Env , typ : TypeId ) -> bool {
0 commit comments