@@ -38,7 +38,7 @@ fn convert_macro<W: std::io::Write>(w: &mut W, macro_path: &syn::Path, stream: &
38
38
if let Some ( s) = types. maybe_resolve_ident ( & struct_for) {
39
39
if !types. crate_types . opaques . get ( & s) . is_some ( ) { return ; }
40
40
writeln ! ( w, "#[no_mangle]" ) . unwrap ( ) ;
41
- writeln ! ( w, "pub extern \" C\" fn {}_write(obj: *const {}) -> crate::c_types::derived::CVec_u8Z {{" , struct_for, struct_for) . unwrap ( ) ;
41
+ writeln ! ( w, "pub extern \" C\" fn {}_write(obj: & {}) -> crate::c_types::derived::CVec_u8Z {{" , struct_for, struct_for) . unwrap ( ) ;
42
42
writeln ! ( w, "\t crate::c_types::serialize_obj(unsafe {{ &(*(*obj).inner) }})" ) . unwrap ( ) ;
43
43
writeln ! ( w, "}}" ) . unwrap ( ) ;
44
44
writeln ! ( w, "#[no_mangle]" ) . unwrap ( ) ;
@@ -58,30 +58,119 @@ fn convert_macro<W: std::io::Write>(w: &mut W, macro_path: &syn::Path, stream: &
58
58
}
59
59
}
60
60
61
- /// Convert "impl trait_path for for_obj { .. }" for manually-mapped types (ie (de)serialization)
62
- fn maybe_convert_trait_impl < W : std:: io:: Write > ( w : & mut W , trait_path : & syn:: Path , for_obj : & syn:: Ident , types : & TypeResolver ) {
63
- if let Some ( t) = types. maybe_resolve_path ( & trait_path, None ) {
64
- let s = types. maybe_resolve_ident ( for_obj) . unwrap ( ) ;
65
- if !types. crate_types . opaques . get ( & s) . is_some ( ) { return ; }
61
+ /// Convert "impl trait_path for for_ty { .. }" for manually-mapped types (ie (de)serialization)
62
+ fn maybe_convert_trait_impl < W : std:: io:: Write > ( w : & mut W , trait_path : & syn:: Path , for_ty : & syn:: Type , types : & mut TypeResolver , generics : & GenericTypes ) {
63
+ if let Some ( t) = types. maybe_resolve_path ( & trait_path, Some ( generics) ) {
64
+ let for_obj;
65
+ let full_obj_path;
66
+ let mut has_inner = false ;
67
+ if let syn:: Type :: Path ( ref p) = for_ty {
68
+ if let Some ( ident) = single_ident_generic_path_to_ident ( & p. path ) {
69
+ for_obj = format ! ( "{}" , ident) ;
70
+ full_obj_path = for_obj. clone ( ) ;
71
+ has_inner = types. c_type_has_inner_from_path ( & types. resolve_path ( & p. path , Some ( generics) ) ) ;
72
+ } else { return ; }
73
+ } else {
74
+ // We assume that anything that isn't a Path is somehow a generic that ends up in our
75
+ // derived-types module.
76
+ let mut for_obj_vec = Vec :: new ( ) ;
77
+ types. write_c_type ( & mut for_obj_vec, for_ty, Some ( generics) , false ) ;
78
+ full_obj_path = String :: from_utf8 ( for_obj_vec) . unwrap ( ) ;
79
+ assert ! ( full_obj_path. starts_with( TypeResolver :: generated_container_path( ) ) ) ;
80
+ for_obj = full_obj_path[ TypeResolver :: generated_container_path ( ) . len ( ) + 2 ..] . into ( ) ;
81
+ }
82
+
66
83
match & t as & str {
67
84
"util::ser::Writeable" => {
68
85
writeln ! ( w, "#[no_mangle]" ) . unwrap ( ) ;
69
- writeln ! ( w, "pub extern \" C\" fn {}_write(obj: *const {}) -> crate::c_types::derived::CVec_u8Z {{" , for_obj, for_obj) . unwrap ( ) ;
70
- writeln ! ( w, "\t crate::c_types::serialize_obj(unsafe {{ &(*(*obj).inner) }})" ) . unwrap ( ) ;
71
- writeln ! ( w, "}}" ) . unwrap ( ) ;
72
- writeln ! ( w, "#[no_mangle]" ) . unwrap ( ) ;
73
- writeln ! ( w, "pub(crate) extern \" C\" fn {}_write_void(obj: *const c_void) -> crate::c_types::derived::CVec_u8Z {{" , for_obj) . unwrap ( ) ;
74
- writeln ! ( w, "\t crate::c_types::serialize_obj(unsafe {{ &*(obj as *const native{}) }})" , for_obj) . unwrap ( ) ;
86
+ writeln ! ( w, "pub extern \" C\" fn {}_write(obj: &{}) -> crate::c_types::derived::CVec_u8Z {{" , for_obj, full_obj_path) . unwrap ( ) ;
87
+
88
+ let ref_type = syn:: Type :: Reference ( syn:: TypeReference {
89
+ and_token : syn:: Token !( & ) ( Span :: call_site ( ) ) , lifetime : None , mutability : None ,
90
+ elem : Box :: new ( for_ty. clone ( ) ) } ) ;
91
+ assert ! ( !types. write_from_c_conversion_new_var( w, & syn:: Ident :: new( "obj" , Span :: call_site( ) ) , & ref_type, Some ( generics) ) ) ;
92
+
93
+ write ! ( w, "\t crate::c_types::serialize_obj(" ) . unwrap ( ) ;
94
+ types. write_from_c_conversion_prefix ( w, & ref_type, Some ( generics) ) ;
95
+ write ! ( w, "unsafe {{ &*obj }}" ) . unwrap ( ) ;
96
+ types. write_from_c_conversion_suffix ( w, & ref_type, Some ( generics) ) ;
97
+ writeln ! ( w, ")" ) . unwrap ( ) ;
98
+
75
99
writeln ! ( w, "}}" ) . unwrap ( ) ;
100
+ if has_inner {
101
+ writeln ! ( w, "#[no_mangle]" ) . unwrap ( ) ;
102
+ writeln ! ( w, "pub(crate) extern \" C\" fn {}_write_void(obj: *const c_void) -> crate::c_types::derived::CVec_u8Z {{" , for_obj) . unwrap ( ) ;
103
+ writeln ! ( w, "\t crate::c_types::serialize_obj(unsafe {{ &*(obj as *const native{}) }})" , for_obj) . unwrap ( ) ;
104
+ writeln ! ( w, "}}" ) . unwrap ( ) ;
105
+ }
76
106
} ,
77
- "util::ser::Readable" => {
107
+ "util::ser::Readable" |"util::ser::ReadableArgs" => {
108
+ // Create the Result<Object, DecodeError> syn::Type
109
+ let mut err_segs = syn:: punctuated:: Punctuated :: new ( ) ;
110
+ err_segs. push ( syn:: PathSegment { ident : syn:: Ident :: new ( "ln" , Span :: call_site ( ) ) , arguments : syn:: PathArguments :: None } ) ;
111
+ err_segs. push ( syn:: PathSegment { ident : syn:: Ident :: new ( "msgs" , Span :: call_site ( ) ) , arguments : syn:: PathArguments :: None } ) ;
112
+ err_segs. push ( syn:: PathSegment { ident : syn:: Ident :: new ( "DecodeError" , Span :: call_site ( ) ) , arguments : syn:: PathArguments :: None } ) ;
113
+ let mut args = syn:: punctuated:: Punctuated :: new ( ) ;
114
+ args. push ( syn:: GenericArgument :: Type ( for_ty. clone ( ) ) ) ;
115
+ args. push ( syn:: GenericArgument :: Type ( syn:: Type :: Path ( syn:: TypePath {
116
+ qself : None , path : syn:: Path {
117
+ leading_colon : Some ( syn:: Token ![ :: ] ( Span :: call_site ( ) ) ) , segments : err_segs,
118
+ }
119
+ } ) ) ) ;
120
+ let mut res_segs = syn:: punctuated:: Punctuated :: new ( ) ;
121
+ res_segs. push ( syn:: PathSegment {
122
+ ident : syn:: Ident :: new ( "Result" , Span :: call_site ( ) ) ,
123
+ arguments : syn:: PathArguments :: AngleBracketed ( syn:: AngleBracketedGenericArguments {
124
+ colon2_token : None , lt_token : syn:: Token ![ <] ( Span :: call_site ( ) ) , args, gt_token : syn:: Token ![ >] ( Span :: call_site ( ) ) ,
125
+ } )
126
+ } ) ;
127
+ let res_ty = syn:: Type :: Path ( syn:: TypePath { qself : None , path : syn:: Path {
128
+ leading_colon : None , segments : res_segs } } ) ;
129
+
78
130
writeln ! ( w, "#[no_mangle]" ) . unwrap ( ) ;
79
- writeln ! ( w, "pub extern \" C\" fn {}_read(ser: crate::c_types::u8slice) -> {} {{" , for_obj, for_obj) . unwrap ( ) ;
80
- writeln ! ( w, "\t if let Ok(res) = crate::c_types::deserialize_obj(ser) {{" ) . unwrap ( ) ;
81
- writeln ! ( w, "\t \t {} {{ inner: Box::into_raw(Box::new(res)), is_owned: true }}" , for_obj) . unwrap ( ) ;
82
- writeln ! ( w, "\t }} else {{" ) . unwrap ( ) ;
83
- writeln ! ( w, "\t \t {} {{ inner: std::ptr::null_mut(), is_owned: true }}" , for_obj) . unwrap ( ) ;
84
- writeln ! ( w, "\t }}\n }}" ) . unwrap ( ) ;
131
+ write ! ( w, "pub extern \" C\" fn {}_read(ser: crate::c_types::u8slice" , for_obj) . unwrap ( ) ;
132
+
133
+ let mut arg_conv = Vec :: new ( ) ;
134
+ if t == "util::ser::ReadableArgs" {
135
+ write ! ( w, ", arg: " ) . unwrap ( ) ;
136
+ assert ! ( trait_path. leading_colon. is_none( ) ) ;
137
+ let args_seg = trait_path. segments . iter ( ) . last ( ) . unwrap ( ) ;
138
+ assert_eq ! ( format!( "{}" , args_seg. ident) , "ReadableArgs" ) ;
139
+ if let syn:: PathArguments :: AngleBracketed ( args) = & args_seg. arguments {
140
+ assert_eq ! ( args. args. len( ) , 1 ) ;
141
+ if let syn:: GenericArgument :: Type ( args_ty) = args. args . iter ( ) . next ( ) . unwrap ( ) {
142
+ types. write_c_type ( w, args_ty, Some ( generics) , false ) ;
143
+
144
+ assert ! ( !types. write_from_c_conversion_new_var( & mut arg_conv, & syn:: Ident :: new( "arg" , Span :: call_site( ) ) , & args_ty, Some ( generics) ) ) ;
145
+
146
+ write ! ( & mut arg_conv, "\t let arg_conv = " ) . unwrap ( ) ;
147
+ types. write_from_c_conversion_prefix ( & mut arg_conv, & args_ty, Some ( generics) ) ;
148
+ write ! ( & mut arg_conv, "arg" ) . unwrap ( ) ;
149
+ types. write_from_c_conversion_suffix ( & mut arg_conv, & args_ty, Some ( generics) ) ;
150
+ } else { unreachable ! ( ) ; }
151
+ } else { unreachable ! ( ) ; }
152
+ }
153
+ write ! ( w, ") -> " ) . unwrap ( ) ;
154
+ types. write_c_type ( w, & res_ty, Some ( generics) , false ) ;
155
+ writeln ! ( w, " {{" ) . unwrap ( ) ;
156
+
157
+ if t == "util::ser::ReadableArgs" {
158
+ w. write ( & arg_conv) . unwrap ( ) ;
159
+ write ! ( w, ";\n \t let res: " ) . unwrap ( ) ;
160
+ // At least in one case we need type annotations here, so provide them.
161
+ types. write_rust_type ( w, Some ( generics) , & res_ty) ;
162
+ writeln ! ( w, " = crate::c_types::deserialize_obj_arg(ser, arg_conv);" ) . unwrap ( ) ;
163
+ } else {
164
+ writeln ! ( w, "\t let res = crate::c_types::deserialize_obj(ser);" ) . unwrap ( ) ;
165
+ }
166
+ write ! ( w, "\t " ) . unwrap ( ) ;
167
+ if types. write_to_c_conversion_new_var ( w, & syn:: Ident :: new ( "res" , Span :: call_site ( ) ) , & res_ty, Some ( generics) , false ) {
168
+ write ! ( w, "\n \t " ) . unwrap ( ) ;
169
+ }
170
+ types. write_to_c_conversion_inline_prefix ( w, & res_ty, Some ( generics) , false ) ;
171
+ write ! ( w, "res" ) . unwrap ( ) ;
172
+ types. write_to_c_conversion_inline_suffix ( w, & res_ty, Some ( generics) , false ) ;
173
+ writeln ! ( w, "\n }}" ) . unwrap ( ) ;
85
174
} ,
86
175
_ => { } ,
87
176
}
@@ -617,6 +706,36 @@ fn writeln_struct<'a, 'b, W: std::io::Write>(w: &mut W, s: &'a syn::ItemStruct,
617
706
///
618
707
/// A few non-crate Traits are hard-coded including Default.
619
708
fn writeln_impl < W : std:: io:: Write > ( w : & mut W , i : & syn:: ItemImpl , types : & mut TypeResolver ) {
709
+ match export_status ( & i. attrs ) {
710
+ ExportStatus :: Export => { } ,
711
+ ExportStatus :: NoExport |ExportStatus :: TestOnly => return ,
712
+ }
713
+
714
+ if let syn:: Type :: Tuple ( _) = & * i. self_ty {
715
+ if types. understood_c_type ( & * i. self_ty , None ) {
716
+ let mut gen_types = GenericTypes :: new ( ) ;
717
+ if !gen_types. learn_generics ( & i. generics , types) {
718
+ eprintln ! ( "Not implementing anything for `impl (..)` due to not understood generics" ) ;
719
+ return ;
720
+ }
721
+
722
+ if i. defaultness . is_some ( ) || i. unsafety . is_some ( ) { unimplemented ! ( ) ; }
723
+ if let Some ( trait_path) = i. trait_ . as_ref ( ) {
724
+ if trait_path. 0 . is_some ( ) { unimplemented ! ( ) ; }
725
+ if types. understood_c_path ( & trait_path. 1 ) {
726
+ eprintln ! ( "Not implementing anything for `impl Trait for (..)` - we only support manual defines" ) ;
727
+ return ;
728
+ } else {
729
+ // Just do a manual implementation:
730
+ maybe_convert_trait_impl ( w, & trait_path. 1 , & * i. self_ty , types, & gen_types) ;
731
+ }
732
+ } else {
733
+ eprintln ! ( "Not implementing anything for plain `impl (..)` block - we only support `impl Trait for (..)` blocks" ) ;
734
+ return ;
735
+ }
736
+ }
737
+ return ;
738
+ }
620
739
if let & syn:: Type :: Path ( ref p) = & * i. self_ty {
621
740
if p. qself . is_some ( ) { unimplemented ! ( ) ; }
622
741
if let Some ( ident) = single_ident_generic_path_to_ident ( & p. path ) {
@@ -672,7 +791,7 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
672
791
writeln ! ( w, "\t \t ret.free = Some({}_free_void);" , ident) . unwrap ( ) ;
673
792
writeln ! ( w, "\t \t ret\n \t }}\n }}" ) . unwrap ( ) ;
674
793
675
- write ! ( w, "#[no_mangle]\n pub extern \" C\" fn {}_as_{}(this_arg: *const {}) -> crate::{} {{\n " , ident, trait_obj. ident, ident, full_trait_path) . unwrap ( ) ;
794
+ write ! ( w, "#[no_mangle]\n pub extern \" C\" fn {}_as_{}(this_arg: & {}) -> crate::{} {{\n " , ident, trait_obj. ident, ident, full_trait_path) . unwrap ( ) ;
676
795
writeln ! ( w, "\t crate::{} {{" , full_trait_path) . unwrap ( ) ;
677
796
writeln ! ( w, "\t \t this_arg: unsafe {{ (*this_arg).inner as *mut c_void }}," ) . unwrap ( ) ;
678
797
writeln ! ( w, "\t \t free: None," ) . unwrap ( ) ;
@@ -838,12 +957,11 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
838
957
} ,
839
958
"PartialEq" => { } ,
840
959
// If we have no generics, try a manual implementation:
841
- _ if p. path . get_ident ( ) . is_some ( ) => maybe_convert_trait_impl ( w, & trait_path. 1 , & ident, types) ,
842
- _ => { } ,
960
+ _ => maybe_convert_trait_impl ( w, & trait_path. 1 , & * i. self_ty , types, & gen_types) ,
843
961
}
844
- } else if p . path . get_ident ( ) . is_some ( ) {
962
+ } else {
845
963
// If we have no generics, try a manual implementation:
846
- maybe_convert_trait_impl ( w, & trait_path. 1 , & ident , types) ;
964
+ maybe_convert_trait_impl ( w, & trait_path. 1 , & * i . self_ty , types, & gen_types ) ;
847
965
}
848
966
} else {
849
967
let declared_type = ( * types. get_declared_type ( & ident) . unwrap ( ) ) . clone ( ) ;
@@ -1438,10 +1556,18 @@ fn main() {
1438
1556
let mut cpp_header_file = std:: fs:: OpenOptions :: new ( ) . write ( true ) . create ( true ) . truncate ( true )
1439
1557
. open ( & args[ 6 ] ) . expect ( "Unable to open new header file" ) ;
1440
1558
1441
- writeln ! ( header_file, "#if defined(__GNUC__)\n #define MUST_USE_STRUCT __attribute__((warn_unused))" ) . unwrap ( ) ;
1442
- writeln ! ( header_file, "#else\n #define MUST_USE_STRUCT\n #endif" ) . unwrap ( ) ;
1443
- writeln ! ( header_file, "#if defined(__GNUC__)\n #define MUST_USE_RES __attribute__((warn_unused_result))" ) . unwrap ( ) ;
1444
- writeln ! ( header_file, "#else\n #define MUST_USE_RES\n #endif" ) . unwrap ( ) ;
1559
+ writeln ! ( header_file, "#if defined(__GNUC__)" ) . unwrap ( ) ;
1560
+ writeln ! ( header_file, "#define MUST_USE_STRUCT __attribute__((warn_unused))" ) . unwrap ( ) ;
1561
+ writeln ! ( header_file, "#define MUST_USE_RES __attribute__((warn_unused_result))" ) . unwrap ( ) ;
1562
+ writeln ! ( header_file, "#else" ) . unwrap ( ) ;
1563
+ writeln ! ( header_file, "#define MUST_USE_STRUCT" ) . unwrap ( ) ;
1564
+ writeln ! ( header_file, "#define MUST_USE_RES" ) . unwrap ( ) ;
1565
+ writeln ! ( header_file, "#endif" ) . unwrap ( ) ;
1566
+ writeln ! ( header_file, "#if defined(__clang__)" ) . unwrap ( ) ;
1567
+ writeln ! ( header_file, "#define NONNULL_PTR _Nonnull" ) . unwrap ( ) ;
1568
+ writeln ! ( header_file, "#else" ) . unwrap ( ) ;
1569
+ writeln ! ( header_file, "#define NONNULL_PTR" ) . unwrap ( ) ;
1570
+ writeln ! ( header_file, "#endif" ) . unwrap ( ) ;
1445
1571
writeln ! ( cpp_header_file, "#include <string.h>\n namespace LDK {{" ) . unwrap ( ) ;
1446
1572
1447
1573
// First parse the full crate's ASTs, caching them so that we can hold references to the AST
0 commit comments