@@ -38,7 +38,7 @@ fn convert_macro<W: std::io::Write>(w: &mut W, macro_path: &syn::Path, stream: &
3838 if let Some ( s) = types. maybe_resolve_ident ( & struct_for) {
3939 if !types. crate_types . opaques . get ( & s) . is_some ( ) { return ; }
4040 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 ( ) ;
4242 writeln ! ( w, "\t crate::c_types::serialize_obj(unsafe {{ &(*(*obj).inner) }})" ) . unwrap ( ) ;
4343 writeln ! ( w, "}}" ) . unwrap ( ) ;
4444 writeln ! ( w, "#[no_mangle]" ) . unwrap ( ) ;
@@ -58,30 +58,119 @@ fn convert_macro<W: std::io::Write>(w: &mut W, macro_path: &syn::Path, stream: &
5858 }
5959}
6060
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+
6683 match & t as & str {
6784 "util::ser::Writeable" => {
6885 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+
7599 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+ }
76106 } ,
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+
78130 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 ( ) ;
85174 } ,
86175 _ => { } ,
87176 }
@@ -617,6 +706,36 @@ fn writeln_struct<'a, 'b, W: std::io::Write>(w: &mut W, s: &'a syn::ItemStruct,
617706///
618707/// A few non-crate Traits are hard-coded including Default.
619708fn 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+ }
620739 if let & syn:: Type :: Path ( ref p) = & * i. self_ty {
621740 if p. qself . is_some ( ) { unimplemented ! ( ) ; }
622741 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
672791 writeln ! ( w, "\t \t ret.free = Some({}_free_void);" , ident) . unwrap ( ) ;
673792 writeln ! ( w, "\t \t ret\n \t }}\n }}" ) . unwrap ( ) ;
674793
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 ( ) ;
676795 writeln ! ( w, "\t crate::{} {{" , full_trait_path) . unwrap ( ) ;
677796 writeln ! ( w, "\t \t this_arg: unsafe {{ (*this_arg).inner as *mut c_void }}," ) . unwrap ( ) ;
678797 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
838957 } ,
839958 "PartialEq" => { } ,
840959 // 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) ,
843961 }
844- } else if p . path . get_ident ( ) . is_some ( ) {
962+ } else {
845963 // 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 ) ;
847965 }
848966 } else {
849967 let declared_type = ( * types. get_declared_type ( & ident) . unwrap ( ) ) . clone ( ) ;
@@ -1438,10 +1556,18 @@ fn main() {
14381556 let mut cpp_header_file = std:: fs:: OpenOptions :: new ( ) . write ( true ) . create ( true ) . truncate ( true )
14391557 . open ( & args[ 6 ] ) . expect ( "Unable to open new header file" ) ;
14401558
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 ( ) ;
14451571 writeln ! ( cpp_header_file, "#include <string.h>\n namespace LDK {{" ) . unwrap ( ) ;
14461572
14471573 // First parse the full crate's ASTs, caching them so that we can hold references to the AST
0 commit comments