@@ -6,10 +6,10 @@ use analysis::function_parameters::{async_param_to_remove, CParameter};
6
6
use analysis:: functions:: { find_function, find_index_to_ignore, finish_function_name} ;
7
7
use analysis:: imports:: Imports ;
8
8
use analysis:: out_parameters:: use_function_return_for_result;
9
- use analysis:: rust_type:: { bounds_rust_type, rust_type} ;
9
+ use analysis:: rust_type:: { bounds_rust_type, rust_type, rust_type_with_scope } ;
10
10
use consts:: TYPE_PARAMETERS_START ;
11
11
use env:: Env ;
12
- use library:: { Class , Function , Fundamental , Nullable , ParameterDirection , Type , TypeId } ;
12
+ use library:: { Class , Concurrency , Function , Fundamental , Nullable , ParameterDirection , Type , TypeId } ;
13
13
use traits:: IntoString ;
14
14
15
15
#[ derive( Clone , Eq , Debug , PartialEq ) ]
@@ -56,6 +56,7 @@ pub struct Bound {
56
56
pub alias : char ,
57
57
pub type_str : String ,
58
58
pub info_for_next_type : bool ,
59
+ pub callback_modified : bool ,
59
60
}
60
61
61
62
#[ derive( Clone , Debug ) ]
@@ -97,14 +98,15 @@ impl Bound {
97
98
alias : TYPE_PARAMETERS_START ,
98
99
type_str : type_str. into_string ( ) ,
99
100
info_for_next_type : false ,
101
+ callback_modified : false ,
100
102
} )
101
103
}
102
104
}
103
105
None
104
106
}
105
107
}
106
108
107
- #[ derive( Debug ) ]
109
+ #[ derive( Debug , Clone ) ]
108
110
pub struct CallbackInfo {
109
111
pub callback_type : String ,
110
112
pub success_parameters : String ,
@@ -119,15 +121,19 @@ impl Bounds {
119
121
func : & Function ,
120
122
par : & CParameter ,
121
123
async : bool ,
124
+ concurrency : Concurrency ,
122
125
) -> ( Option < String > , Option < CallbackInfo > ) {
123
126
let type_name = bounds_rust_type ( env, par. typ ) ;
124
127
let mut type_string = if async & & async_param_to_remove ( & par. name ) {
125
128
return ( None , None ) ;
129
+ } else if type_name. is_err ( ) {
130
+ return ( None , None )
126
131
} else {
127
132
type_name. into_string ( )
128
133
} ;
129
134
let mut callback_info = None ;
130
135
let mut ret = None ;
136
+ let mut need_is_into_check = false ;
131
137
if !par. instance_parameter && par. direction != ParameterDirection :: Out {
132
138
if let Some ( bound_type) = Bounds :: type_for ( env, par. typ , par. nullable ) {
133
139
ret = Some ( Bounds :: get_to_glib_extra ( & bound_type) ) ;
@@ -154,13 +160,55 @@ impl Bounds {
154
160
bound_name,
155
161
} ) ;
156
162
}
163
+ } else if par. c_type == "GDestroyNotify" ||
164
+ env. library . type_ ( par. typ ) . is_function ( ) {
165
+ need_is_into_check = par. c_type != "GDestroyNotify" ;
166
+ if let Type :: Function ( _) = env. library . type_ ( par. typ ) {
167
+ type_string = rust_type_with_scope ( env, par. typ , par. scope , concurrency)
168
+ . into_string ( ) ;
169
+ let bound_name = * self . unused . front ( ) . unwrap ( ) ;
170
+ callback_info = Some ( CallbackInfo {
171
+ callback_type : type_string. clone ( ) ,
172
+ success_parameters : String :: new ( ) ,
173
+ error_parameters : String :: new ( ) ,
174
+ bound_name,
175
+ } ) ;
176
+ }
157
177
}
158
- if !self . add_parameter ( & par. name , & type_string, bound_type, async ) {
178
+ if par. c_type != "GDestroyNotify" &&
179
+ !self . add_parameter ( & par. name , & type_string, bound_type, async ) {
159
180
panic ! (
160
181
"Too many type constraints for {}" ,
161
182
func. c_identifier. as_ref( ) . unwrap( )
162
183
)
163
184
}
185
+ if need_is_into_check {
186
+ if let Some ( x) = if let Some ( ref mut last) = self . used . last_mut ( ) {
187
+ if last. bound_type . is_into ( ) {
188
+ let mut new_one = ( * last) . clone ( ) ;
189
+ new_one. alias = self . unused . pop_front ( ) . expect ( "no available bound" ) ;
190
+ new_one. type_str = last. alias . to_string ( ) ;
191
+ new_one. parameter_name = last. parameter_name . clone ( ) ;
192
+ // When we create a new bound for a callback which can be NULL,
193
+ // we need to generate two new bounds instead of just one. This flag
194
+ // allows us to know it so we can prevent its "generation" in the
195
+ // codegen part (we don't need the `Into<>` part in a few parts of the
196
+ // code).
197
+ new_one. callback_modified = true ;
198
+
199
+ last. bound_type = BoundType :: NoWrapper ;
200
+ last. parameter_name = String :: new ( ) ;
201
+
202
+ Some ( new_one)
203
+ } else {
204
+ None
205
+ }
206
+ } else {
207
+ None
208
+ } {
209
+ self . used . push ( x) ;
210
+ }
211
+ }
164
212
}
165
213
} else if par. instance_parameter {
166
214
if let Some ( bound_type) = Bounds :: type_for ( env, par. typ , par. nullable ) {
@@ -195,6 +243,8 @@ impl Bounds {
195
243
Type :: Interface ( ..) => Some ( Into ( Some ( '_' ) , Some ( Box :: new ( IsA ( None ) ) ) ) ) ,
196
244
Type :: List ( _) | Type :: SList ( _) | Type :: CArray ( _) => None ,
197
245
Type :: Fundamental ( _) if * nullable => Some ( Into ( None , None ) ) ,
246
+ Type :: Function ( _) if * nullable => Some ( Into ( None , None ) ) ,
247
+ Type :: Function ( _) if !* nullable => Some ( NoWrapper ) ,
198
248
_ if !* nullable => None ,
199
249
_ => Some ( Into ( Some ( '_' ) , None ) ) ,
200
250
}
@@ -217,6 +267,7 @@ impl Bounds {
217
267
alias,
218
268
type_str : type_str. to_string ( ) ,
219
269
info_for_next_type : false ,
270
+ callback_modified : false ,
220
271
} ) ;
221
272
return true ;
222
273
}
@@ -244,6 +295,7 @@ impl Bounds {
244
295
alias,
245
296
type_str : type_str. to_owned ( ) ,
246
297
info_for_next_type : true ,
298
+ callback_modified : false ,
247
299
} ) ;
248
300
alias. to_string ( )
249
301
} else {
@@ -259,6 +311,7 @@ impl Bounds {
259
311
alias,
260
312
type_str : type_str. to_owned ( ) ,
261
313
info_for_next_type : false ,
314
+ callback_modified : false ,
262
315
} ) ;
263
316
true
264
317
} else {
0 commit comments