@@ -59,22 +59,22 @@ fn convert_macro<W: std::io::Write>(w: &mut W, macro_path: &syn::Path, stream: &
59
59
}
60
60
61
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 ) {
63
- if let Some ( t) = types. maybe_resolve_path ( & trait_path, None ) {
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
64
let for_obj;
65
65
let full_obj_path;
66
66
let mut has_inner = false ;
67
67
if let syn:: Type :: Path ( ref p) = for_ty {
68
68
if let Some ( ident) = p. path . get_ident ( ) {
69
69
for_obj = format ! ( "{}" , ident) ;
70
70
full_obj_path = for_obj. clone ( ) ;
71
- has_inner = types. c_type_has_inner_from_path ( & types. resolve_path ( & p. path , None ) ) ;
71
+ has_inner = types. c_type_has_inner_from_path ( & types. resolve_path ( & p. path , Some ( generics ) ) ) ;
72
72
} else { return ; }
73
73
} else {
74
74
// We assume that anything that isn't a Path is somehow a generic that ends up in our
75
75
// derived-types module.
76
76
let mut for_obj_vec = Vec :: new ( ) ;
77
- types. write_c_type ( & mut for_obj_vec, for_ty, None , false ) ;
77
+ types. write_c_type ( & mut for_obj_vec, for_ty, Some ( generics ) , false ) ;
78
78
full_obj_path = String :: from_utf8 ( for_obj_vec) . unwrap ( ) ;
79
79
assert ! ( full_obj_path. starts_with( TypeResolver :: generated_container_path( ) ) ) ;
80
80
for_obj = full_obj_path[ TypeResolver :: generated_container_path ( ) . len ( ) + 2 ..] . into ( ) ;
@@ -88,12 +88,12 @@ fn maybe_convert_trait_impl<W: std::io::Write>(w: &mut W, trait_path: &syn::Path
88
88
let ref_type = syn:: Type :: Reference ( syn:: TypeReference {
89
89
and_token : syn:: Token !( & ) ( Span :: call_site ( ) ) , lifetime : None , mutability : None ,
90
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, None ) ) ;
91
+ assert ! ( !types. write_from_c_conversion_new_var( w, & syn:: Ident :: new( "obj" , Span :: call_site( ) ) , & ref_type, Some ( generics ) ) ) ;
92
92
93
93
write ! ( w, "\t crate::c_types::serialize_obj(" ) . unwrap ( ) ;
94
- types. write_from_c_conversion_prefix ( w, & ref_type, None ) ;
94
+ types. write_from_c_conversion_prefix ( w, & ref_type, Some ( generics ) ) ;
95
95
write ! ( w, "unsafe {{ &*obj }}" ) . unwrap ( ) ;
96
- types. write_from_c_conversion_suffix ( w, & ref_type, None ) ;
96
+ types. write_from_c_conversion_suffix ( w, & ref_type, Some ( generics ) ) ;
97
97
writeln ! ( w, ")" ) . unwrap ( ) ;
98
98
99
99
writeln ! ( w, "}}" ) . unwrap ( ) ;
@@ -104,7 +104,7 @@ fn maybe_convert_trait_impl<W: std::io::Write>(w: &mut W, trait_path: &syn::Path
104
104
writeln ! ( w, "}}" ) . unwrap ( ) ;
105
105
}
106
106
} ,
107
- "util::ser::Readable" => {
107
+ "util::ser::Readable" | "util::ser::ReadableArgs" => {
108
108
// Create the Result<Object, DecodeError> syn::Type
109
109
let mut err_segs = syn:: punctuated:: Punctuated :: new ( ) ;
110
110
err_segs. push ( syn:: PathSegment { ident : syn:: Ident :: new ( "ln" , Span :: call_site ( ) ) , arguments : syn:: PathArguments :: None } ) ;
@@ -128,17 +128,48 @@ fn maybe_convert_trait_impl<W: std::io::Write>(w: &mut W, trait_path: &syn::Path
128
128
leading_colon : None , segments : res_segs } } ) ;
129
129
130
130
writeln ! ( w, "#[no_mangle]" ) . unwrap ( ) ;
131
- write ! ( w, "pub extern \" C\" fn {}_read(ser: crate::c_types::u8slice) -> " , for_obj) . unwrap ( ) ;
132
- types. write_c_type ( w, & res_ty, None , false ) ;
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 ) ;
133
155
writeln ! ( w, " {{" ) . unwrap ( ) ;
134
- writeln ! ( w, "\t let res = crate::c_types::deserialize_obj(ser);" ) . 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
+ }
135
166
write ! ( w, "\t " ) . unwrap ( ) ;
136
- if types. write_to_c_conversion_new_var ( w, & syn:: Ident :: new ( "res" , Span :: call_site ( ) ) , & res_ty, None , false ) {
167
+ if types. write_to_c_conversion_new_var ( w, & syn:: Ident :: new ( "res" , Span :: call_site ( ) ) , & res_ty, Some ( generics ) , false ) {
137
168
write ! ( w, "\n \t " ) . unwrap ( ) ;
138
169
}
139
- types. write_to_c_conversion_inline_prefix ( w, & res_ty, None , false ) ;
170
+ types. write_to_c_conversion_inline_prefix ( w, & res_ty, Some ( generics ) , false ) ;
140
171
write ! ( w, "res" ) . unwrap ( ) ;
141
- types. write_to_c_conversion_inline_suffix ( w, & res_ty, None , false ) ;
172
+ types. write_to_c_conversion_inline_suffix ( w, & res_ty, Some ( generics ) , false ) ;
142
173
writeln ! ( w, "\n }}" ) . unwrap ( ) ;
143
174
} ,
144
175
_ => { } ,
@@ -675,6 +706,31 @@ fn writeln_struct<'a, 'b, W: std::io::Write>(w: &mut W, s: &'a syn::ItemStruct,
675
706
///
676
707
/// A few non-crate Traits are hard-coded including Default.
677
708
fn writeln_impl < W : std:: io:: Write > ( w : & mut W , i : & syn:: ItemImpl , types : & mut TypeResolver ) {
709
+ if let syn:: Type :: Tuple ( _) = & * i. self_ty {
710
+ if types. understood_c_type ( & * i. self_ty , None ) {
711
+ let mut gen_types = GenericTypes :: new ( ) ;
712
+ if !gen_types. learn_generics ( & i. generics , types) {
713
+ eprintln ! ( "Not implementing anything for `impl (..)` due to not understood generics" ) ;
714
+ return ;
715
+ }
716
+
717
+ if i. defaultness . is_some ( ) || i. unsafety . is_some ( ) { unimplemented ! ( ) ; }
718
+ if let Some ( trait_path) = i. trait_ . as_ref ( ) {
719
+ if trait_path. 0 . is_some ( ) { unimplemented ! ( ) ; }
720
+ if types. understood_c_path ( & trait_path. 1 ) {
721
+ eprintln ! ( "Not implementing anything for `impl Trait for (..)` - we only support manual defines" ) ;
722
+ return ;
723
+ } else {
724
+ // Just do a manual implementation:
725
+ maybe_convert_trait_impl ( w, & trait_path. 1 , & * i. self_ty , types, & gen_types) ;
726
+ }
727
+ } else {
728
+ eprintln ! ( "Not implementing anything for plain `impl (..)` block - we only support `impl Trait for (..)` blocks" ) ;
729
+ return ;
730
+ }
731
+ }
732
+ return ;
733
+ }
678
734
if let & syn:: Type :: Path ( ref p) = & * i. self_ty {
679
735
if p. qself . is_some ( ) { unimplemented ! ( ) ; }
680
736
if let Some ( ident) = single_ident_generic_path_to_ident ( & p. path ) {
@@ -896,12 +952,12 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
896
952
} ,
897
953
"PartialEq" => { } ,
898
954
// If we have no generics, try a manual implementation:
899
- _ if p. path . get_ident ( ) . is_some ( ) => maybe_convert_trait_impl ( w, & trait_path. 1 , & * i. self_ty , types) ,
955
+ _ if p. path . get_ident ( ) . is_some ( ) => maybe_convert_trait_impl ( w, & trait_path. 1 , & * i. self_ty , types, & gen_types ) ,
900
956
_ => { } ,
901
957
}
902
958
} else if p. path . get_ident ( ) . is_some ( ) {
903
959
// If we have no generics, try a manual implementation:
904
- maybe_convert_trait_impl ( w, & trait_path. 1 , & * i. self_ty , types) ;
960
+ maybe_convert_trait_impl ( w, & trait_path. 1 , & * i. self_ty , types, & gen_types ) ;
905
961
}
906
962
} else {
907
963
let declared_type = ( * types. get_declared_type ( & ident) . unwrap ( ) ) . clone ( ) ;
0 commit comments