@@ -148,6 +148,9 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty
148
148
}
149
149
writeln_docs ( w, & t. attrs , "" ) ;
150
150
151
+ let mut gen_types = GenericTypes :: new ( ) ;
152
+ assert ! ( gen_types. learn_generics( & t. generics, types) ) ;
153
+
151
154
writeln ! ( w, "#[repr(C)]\n pub struct {} {{" , trait_name) . unwrap ( ) ;
152
155
writeln ! ( w, "\t pub this_arg: *mut c_void," ) . unwrap ( ) ;
153
156
let associated_types = learn_associated_types ( t) ;
@@ -158,15 +161,17 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty
158
161
match export_status ( & m. attrs ) {
159
162
ExportStatus :: NoExport => {
160
163
// NoExport in this context means we'll hit an unimplemented!() at runtime,
161
- // so add a comment noting that this needs to change in the output.
162
- writeln ! ( w, "\t //XXX: Need to export {}" , m. sig. ident) . unwrap ( ) ;
163
- continue ;
164
+ // so bail out.
165
+ unimplemented ! ( ) ;
164
166
} ,
165
167
ExportStatus :: Export => { } ,
166
168
ExportStatus :: TestOnly => continue ,
167
169
}
168
170
if m. default . is_some ( ) { unimplemented ! ( ) ; }
169
171
172
+ gen_types. push_ctx ( ) ;
173
+ assert ! ( gen_types. learn_generics( & m. sig. generics, types) ) ;
174
+
170
175
writeln_docs ( w, & m. attrs , "\t " ) ;
171
176
172
177
if let syn:: ReturnType :: Type ( _, rtype) = & m. sig . output {
@@ -183,7 +188,7 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty
183
188
// called when the trait method is called which allows updating on the fly.
184
189
write ! ( w, "\t pub {}: " , m. sig. ident) . unwrap ( ) ;
185
190
generated_fields. push ( format ! ( "{}" , m. sig. ident) ) ;
186
- types. write_c_type ( w, & * r. elem , None , false ) ;
191
+ types. write_c_type ( w, & * r. elem , Some ( & gen_types ) , false ) ;
187
192
writeln ! ( w, "," ) . unwrap ( ) ;
188
193
writeln ! ( w, "\t /// Fill in the {} field as a reference to it will be given to Rust after this returns" , m. sig. ident) . unwrap ( ) ;
189
194
writeln ! ( w, "\t /// Note that this takes a pointer to this object, not the this_ptr like other methods do" ) . unwrap ( ) ;
@@ -195,6 +200,7 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty
195
200
// which does not compile since Thing is not defined before it is used.
196
201
writeln ! ( extra_headers, "struct LDK{};" , trait_name) . unwrap ( ) ;
197
202
writeln ! ( extra_headers, "typedef struct LDK{} LDK{};" , trait_name, trait_name) . unwrap ( ) ;
203
+ gen_types. pop_ctx ( ) ;
198
204
continue ;
199
205
}
200
206
// Sadly, this currently doesn't do what we want, but it should be easy to get
@@ -204,8 +210,10 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty
204
210
205
211
write ! ( w, "\t pub {}: extern \" C\" fn (" , m. sig. ident) . unwrap ( ) ;
206
212
generated_fields. push ( format ! ( "{}" , m. sig. ident) ) ;
207
- write_method_params ( w, & m. sig , & associated_types, "c_void" , types, None , true , false ) ;
213
+ write_method_params ( w, & m. sig , & associated_types, "c_void" , types, Some ( & gen_types ) , true , false ) ;
208
214
writeln ! ( w, "," ) . unwrap ( ) ;
215
+
216
+ gen_types. pop_ctx ( ) ;
209
217
} ,
210
218
& syn:: TraitItem :: Type ( _) => { } ,
211
219
_ => unimplemented ! ( ) ,
@@ -218,7 +226,8 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty
218
226
generated_fields. push( "clone" . to_owned( ) ) ;
219
227
} ,
220
228
( "std::cmp::Eq" , _) => {
221
- writeln!( w, "\t pub eq: extern \" C\" fn (this_arg: *const c_void, other_arg: *const c_void) -> bool," ) . unwrap( ) ;
229
+ writeln!( w, "\t pub eq: extern \" C\" fn (this_arg: *const c_void, other_arg: &{}) -> bool," , trait_name) . unwrap( ) ;
230
+ writeln!( extra_headers, "typedef struct LDK{} LDK{};" , trait_name, trait_name) . unwrap( ) ;
222
231
generated_fields. push( "eq" . to_owned( ) ) ;
223
232
} ,
224
233
( "std::hash::Hash" , _) => {
@@ -243,21 +252,25 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty
243
252
( "std::cmp::Eq" , _) => {
244
253
writeln!( w, "impl std::cmp::Eq for {} {{}}" , trait_name) . unwrap( ) ;
245
254
writeln!( w, "impl std::cmp::PartialEq for {} {{" , trait_name) . unwrap( ) ;
246
- writeln!( w, "\t fn eq(&self, o: &Self) -> bool {{ (self.eq)(self.this_arg, o.this_arg ) }}\n }}" ) . unwrap( ) ;
255
+ writeln!( w, "\t fn eq(&self, o: &Self) -> bool {{ (self.eq)(self.this_arg, o) }}\n }}" ) . unwrap( ) ;
247
256
} ,
248
257
( "std::hash::Hash" , _) => {
249
258
writeln!( w, "impl std::hash::Hash for {} {{" , trait_name) . unwrap( ) ;
250
259
writeln!( w, "\t fn hash<H: std::hash::Hasher>(&self, hasher: &mut H) {{ hasher.write_u64((self.hash)(self.this_arg)) }}\n }}" ) . unwrap( ) ;
251
260
} ,
252
261
( "Clone" , _) => {
253
- writeln!( w, "impl Clone for {} {{" , trait_name ) . unwrap( ) ;
254
- writeln!( w, "\t fn clone(&self ) -> Self {{" ) . unwrap( ) ;
255
- writeln!( w, "\t \t Self {{" ) . unwrap( ) ;
256
- writeln!( w, "\t \t this_arg: if let Some(f) = self .clone {{ (f)(self .this_arg) }} else {{ self .this_arg }}," ) . unwrap( ) ;
262
+ writeln!( w, "#[no_mangle]" ) . unwrap( ) ;
263
+ writeln!( w, "pub extern \" C \" fn {}_clone(orig: &{} ) -> {} {{" , trait_name , trait_name , trait_name ) . unwrap( ) ;
264
+ writeln!( w, "\t {} {{" , trait_name ) . unwrap( ) ;
265
+ writeln!( w, "\t \t this_arg: if let Some(f) = orig .clone {{ (f)(orig .this_arg) }} else {{ orig .this_arg }}," ) . unwrap( ) ;
257
266
for field in generated_fields. iter( ) {
258
- writeln!( w, "\t \t \t {}: self .{}.clone()," , field, field) . unwrap( ) ;
267
+ writeln!( w, "\t \t {}: orig .{}.clone()," , field, field) . unwrap( ) ;
259
268
}
260
- writeln!( w, "\t \t }}\n \t }}\n }}" ) . unwrap( ) ;
269
+ writeln!( w, "\t }}\n }}" ) . unwrap( ) ;
270
+ writeln!( w, "impl Clone for {} {{" , trait_name) . unwrap( ) ;
271
+ writeln!( w, "\t fn clone(&self) -> Self {{" ) . unwrap( ) ;
272
+ writeln!( w, "\t \t {}_clone(self)" , trait_name) . unwrap( ) ;
273
+ writeln!( w, "\t }}\n }}" ) . unwrap( ) ;
261
274
} ,
262
275
( s, i) => {
263
276
if s != "util::events::MessageSendEventsProvider" { unimplemented!( ) ; }
@@ -284,8 +297,10 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty
284
297
m. sig . abi . is_some ( ) || m. sig . variadic . is_some ( ) {
285
298
unimplemented ! ( ) ;
286
299
}
300
+ gen_types. push_ctx ( ) ;
301
+ assert ! ( gen_types. learn_generics( & m. sig. generics, types) ) ;
287
302
write ! ( w, "\t fn {}" , m. sig. ident) . unwrap ( ) ;
288
- types. write_rust_generic_param ( w, m. sig . generics . params . iter ( ) ) ;
303
+ types. write_rust_generic_param ( w, Some ( & gen_types ) , m. sig . generics . params . iter ( ) ) ;
289
304
write ! ( w, "(" ) . unwrap ( ) ;
290
305
for inp in m. sig . inputs . iter ( ) {
291
306
match inp {
@@ -309,27 +324,26 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty
309
324
ident. mutability . is_some ( ) || ident. subpat . is_some ( ) {
310
325
unimplemented ! ( ) ;
311
326
}
312
- write ! ( w, ", {}{}: " , if types. skip_arg( & * arg. ty, None ) { "_" } else { "" } , ident. ident) . unwrap ( ) ;
327
+ write ! ( w, ", {}{}: " , if types. skip_arg( & * arg. ty, Some ( & gen_types ) ) { "_" } else { "" } , ident. ident) . unwrap ( ) ;
313
328
}
314
329
_ => unimplemented ! ( ) ,
315
330
}
316
- types. write_rust_type ( w, & * arg. ty ) ;
331
+ types. write_rust_type ( w, Some ( & gen_types ) , & * arg. ty ) ;
317
332
}
318
333
}
319
334
}
320
335
write ! ( w, ")" ) . unwrap ( ) ;
321
336
match & m. sig . output {
322
337
syn:: ReturnType :: Type ( _, rtype) => {
323
338
write ! ( w, " -> " ) . unwrap ( ) ;
324
- types. write_rust_type ( w, & * rtype)
339
+ types. write_rust_type ( w, Some ( & gen_types ) , & * rtype)
325
340
} ,
326
341
_ => { } ,
327
342
}
328
343
write ! ( w, " {{\n \t \t " ) . unwrap ( ) ;
329
344
match export_status ( & m. attrs ) {
330
345
ExportStatus :: NoExport => {
331
- writeln ! ( w, "unimplemented!();\n \t }}" ) . unwrap ( ) ;
332
- continue ;
346
+ unimplemented ! ( ) ;
333
347
} ,
334
348
_ => { } ,
335
349
}
@@ -339,25 +353,27 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty
339
353
writeln ! ( w, "if let Some(f) = self.set_{} {{" , m. sig. ident) . unwrap ( ) ;
340
354
writeln ! ( w, "\t \t \t (f)(self);" ) . unwrap ( ) ;
341
355
write ! ( w, "\t \t }}\n \t \t " ) . unwrap ( ) ;
342
- types. write_from_c_conversion_to_ref_prefix ( w, & * r. elem , None ) ;
356
+ types. write_from_c_conversion_to_ref_prefix ( w, & * r. elem , Some ( & gen_types ) ) ;
343
357
write ! ( w, "self.{}" , m. sig. ident) . unwrap ( ) ;
344
- types. write_from_c_conversion_to_ref_suffix ( w, & * r. elem , None ) ;
358
+ types. write_from_c_conversion_to_ref_suffix ( w, & * r. elem , Some ( & gen_types ) ) ;
345
359
writeln ! ( w, "\n \t }}" ) . unwrap ( ) ;
360
+ gen_types. pop_ctx ( ) ;
346
361
continue ;
347
362
}
348
363
}
349
- write_method_var_decl_body ( w, & m. sig , "\t " , types, None , true ) ;
364
+ write_method_var_decl_body ( w, & m. sig , "\t " , types, Some ( & gen_types ) , true ) ;
350
365
write ! ( w, "(self.{})(" , m. sig. ident) . unwrap ( ) ;
351
- write_method_call_params ( w, & m. sig , & associated_types, "\t " , types, None , "" , true ) ;
366
+ write_method_call_params ( w, & m. sig , & associated_types, "\t " , types, Some ( & gen_types ) , "" , true ) ;
352
367
353
368
writeln ! ( w, "\n \t }}" ) . unwrap ( ) ;
369
+ gen_types. pop_ctx ( ) ;
354
370
} ,
355
371
& syn:: TraitItem :: Type ( ref t) => {
356
372
if t. default . is_some ( ) || t. generics . lt_token . is_some ( ) { unimplemented ! ( ) ; }
357
373
let mut bounds_iter = t. bounds . iter ( ) ;
358
374
match bounds_iter. next ( ) . unwrap ( ) {
359
375
syn:: TypeParamBound :: Trait ( tr) => {
360
- writeln ! ( w, "\t type {} = crate::{};" , t. ident, types. resolve_path( & tr. path, None ) ) . unwrap ( ) ;
376
+ writeln ! ( w, "\t type {} = crate::{};" , t. ident, types. resolve_path( & tr. path, Some ( & gen_types ) ) ) . unwrap ( ) ;
361
377
} ,
362
378
_ => unimplemented ! ( ) ,
363
379
}
@@ -439,6 +455,10 @@ fn writeln_opaque<W: std::io::Write>(w: &mut W, ident: &syn::Ident, struct_name:
439
455
writeln ! ( w, "pub(crate) extern \" C\" fn {}_clone_void(this_ptr: *const c_void) -> *mut c_void {{" , struct_name) . unwrap ( ) ;
440
456
writeln ! ( w, "\t Box::into_raw(Box::new(unsafe {{ (*(this_ptr as *mut native{})).clone() }})) as *mut c_void" , struct_name) . unwrap ( ) ;
441
457
writeln ! ( w, "}}" ) . unwrap ( ) ;
458
+ writeln ! ( w, "#[no_mangle]" ) . unwrap ( ) ;
459
+ writeln ! ( w, "pub extern \" C\" fn {}_clone(orig: &{}) -> {} {{" , struct_name, struct_name, struct_name) . unwrap ( ) ;
460
+ writeln ! ( w, "\t {} {{ inner: Box::into_raw(Box::new(unsafe {{ &*orig.inner }}.clone())), is_owned: true }}" , struct_name) . unwrap ( ) ;
461
+ writeln ! ( w, "}}" ) . unwrap ( ) ;
442
462
break ' attr_loop;
443
463
}
444
464
}
@@ -980,6 +1000,10 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type
980
1000
if needs_free {
981
1001
writeln ! ( w, "#[no_mangle]\n pub extern \" C\" fn {}_free(this_ptr: {}) {{ }}" , e. ident, e. ident) . unwrap ( ) ;
982
1002
}
1003
+ writeln ! ( w, "#[no_mangle]" ) . unwrap ( ) ;
1004
+ writeln ! ( w, "pub extern \" C\" fn {}_clone(orig: &{}) -> {} {{" , e. ident, e. ident, e. ident) . unwrap ( ) ;
1005
+ writeln ! ( w, "\t orig.clone()" ) . unwrap ( ) ;
1006
+ writeln ! ( w, "}}" ) . unwrap ( ) ;
983
1007
write_cpp_wrapper ( cpp_headers, & format ! ( "{}" , e. ident) , needs_free) ;
984
1008
}
985
1009
0 commit comments