1- pub mod enums;
2-
3- use crate :: attr;
41use proc_macro2:: TokenStream ;
52use syn;
3+ use syn:: Field ;
4+
5+ use crate :: attr;
6+
7+ pub mod enums;
68
79pub fn read_fields ( fields : & syn:: Fields )
8- -> TokenStream {
10+ -> TokenStream {
911 match * fields {
1012 syn:: Fields :: Named ( ref fields_named) => read_named_fields ( fields_named) ,
1113 syn:: Fields :: Unnamed ( ref fields_unnamed) => read_unnamed_fields ( fields_unnamed) ,
@@ -14,7 +16,7 @@ pub fn read_fields(fields: &syn::Fields)
1416}
1517
1618pub fn write_fields ( fields : & syn:: Fields )
17- -> TokenStream {
19+ -> TokenStream {
1820 match * fields {
1921 syn:: Fields :: Named ( ref fields_named) => write_named_fields ( fields_named) ,
2022 syn:: Fields :: Unnamed ( ref fields_unnamed) => write_unnamed_fields ( fields_unnamed) ,
@@ -32,9 +34,9 @@ fn read_named_fields(fields_named: &syn::FieldsNamed)
3234 let field_initializers: Vec < _ > = fields_named. named . iter ( ) . map ( |field| {
3335 let field_name = & field. ident ;
3436 let field_ty = & field. ty ;
35- // This field may store the length prefix of another field.
37+ // This field may store the length prefix of one or more other field.
3638 let update_hints = update_hints_after_read ( field, & fields_named. named ) ;
37- let update_hints_fixed = update_hints__fixed_after_read ( field, & fields_named. named ) ;
39+ let update_hints_fixed = update_hint_fixed_length ( field, & fields_named. named ) ;
3840
3941 quote ! {
4042 #field_name : {
@@ -53,26 +55,30 @@ fn read_named_fields(fields_named: &syn::FieldsNamed)
5355fn update_hints_after_read < ' a > ( field : & ' a syn:: Field ,
5456 fields : impl IntoIterator < Item =& ' a syn:: Field > + Clone )
5557 -> TokenStream {
56- if let Some ( ( length_prefix_of , kind , prefix_subfield_names ) ) = length_prefix_of ( field, fields. clone ( ) ) {
58+ let hint_setters = length_prefix_of ( field, fields. clone ( ) ) . iter ( ) . map ( | ( length_prefix_of , kind , prefix_subfield_names ) | {
5759 let kind = kind. path_expr ( ) ;
60+ quote ! {
61+ __hints. set_field_length( #length_prefix_of,
62+ ( parcel #( . #prefix_subfield_names) * ) . clone( ) as usize ,
63+ #kind) ;
64+ }
65+ } ) . collect :: < Vec < TokenStream > > ( ) ;
5866
67+ if hint_setters. is_empty ( ) {
68+ quote ! { }
69+ } else {
5970 quote ! {
6071 if let Ok ( parcel) = res. as_ref( ) {
61- __hints. set_field_length( #length_prefix_of,
62- ( parcel #( . #prefix_subfield_names) * ) . clone( ) as usize ,
63- #kind) ;
72+ #( #hint_setters) ; *
6473 }
6574 }
66- } else {
67- quote ! { }
6875 }
6976}
7077
71- fn update_hints__fixed_after_read < ' a > ( field : & ' a syn:: Field ,
72- fields : impl IntoIterator < Item =& ' a syn:: Field > + Clone )
73- -> TokenStream {
74-
75- if let Some ( attr:: Protocol :: FixedLength ( length) ) = attr:: protocol ( & field. attrs ) {
78+ fn update_hint_fixed_length < ' a > ( field : & ' a syn:: Field ,
79+ fields : impl IntoIterator < Item =& ' a syn:: Field > + Clone )
80+ -> TokenStream {
81+ if let Some ( attr:: Protocol :: FixedLength ( length) ) = attr:: protocol ( & field. attrs ) {
7682 let position = fields. clone ( ) . into_iter ( ) . position ( |f| f == field) . unwrap ( ) ;
7783
7884 quote ! {
@@ -85,20 +91,26 @@ fn update_hints__fixed_after_read<'a>(field: &'a syn::Field,
8591
8692fn update_hints_after_write < ' a > ( field : & ' a syn:: Field ,
8793 fields : impl IntoIterator < Item =& ' a syn:: Field > + Clone )
88- -> TokenStream {
89- if let Some ( ( length_prefix_of , kind , prefix_subfield_names ) ) = length_prefix_of ( field, fields. clone ( ) ) {
94+ -> TokenStream {
95+ let hint_setters = length_prefix_of ( field, fields. clone ( ) ) . iter ( ) . map ( | ( length_prefix_of , kind , prefix_subfield_names ) | {
9096 let field_name = & field. ident ;
9197 let kind = kind. path_expr ( ) ;
9298
9399 quote ! {
94- if let Ok ( ( ) ) = res {
95100 __hints. set_field_length( #length_prefix_of,
96101 ( self . #field_name #( . #prefix_subfield_names) * ) . clone( ) as usize ,
97102 #kind) ;
98- }
99103 }
104+ } ) . collect :: < Vec < TokenStream > > ( ) ;
105+
106+ if hint_setters. is_empty ( ) {
107+ quote ! { }
100108 } else {
101- quote ! { }
109+ quote ! {
110+ if let Ok ( ( ) ) = res {
111+ #( #hint_setters) ; *
112+ }
113+ }
102114 }
103115}
104116
@@ -110,33 +122,33 @@ fn update_hints_after_write<'a>(field: &'a syn::Field,
110122/// Returns the field index of the field whose length is specified.
111123fn length_prefix_of < ' a > ( field : & ' a syn:: Field ,
112124 fields : impl IntoIterator < Item =& ' a syn:: Field > + Clone )
113- -> Option < ( usize , attr:: LengthPrefixKind , Vec < syn:: Ident > ) > {
125+ -> Vec < ( usize , attr:: LengthPrefixKind , Vec < syn:: Ident > ) > {
114126 let potential_prefix = field. ident . as_ref ( ) ;
115127
116- let prefix_of = fields. clone ( ) . into_iter ( ) . find ( |potential_prefix_of| {
128+ let prefixes_of : Vec < & ' a Field > = fields. clone ( ) . into_iter ( ) . filter ( |potential_prefix_of| {
117129 match attr:: protocol ( & potential_prefix_of. attrs ) {
118130 Some ( attr:: Protocol :: LengthPrefix { ref prefix_field_name, .. } ) => {
119131 if !fields. clone ( ) . into_iter ( ) . any ( |f| f. ident . as_ref ( ) == Some ( prefix_field_name) ) {
120132 panic ! ( "length prefix is invalid: there is no sibling field named '{}" , prefix_field_name) ;
121133 }
122134
123135 potential_prefix == Some ( prefix_field_name)
124- } ,
136+ }
125137 _ => false ,
126138 }
127- } ) ;
128-
129- if let Some ( prefix_of ) = prefix_of {
130- let prefix_of_index = fields . clone ( ) . into_iter ( ) . position ( |f| f == prefix_of ) . unwrap ( ) ;
131- match attr :: protocol ( & prefix_of . attrs ) . unwrap ( ) {
132- attr :: Protocol :: LengthPrefix { kind , prefix_subfield_names , .. } => {
133- Some ( ( prefix_of_index , kind . clone ( ) , prefix_subfield_names ) )
134- } ,
135- _ => unreachable ! ( ) ,
136- }
137- } else {
138- None
139- }
139+ } ) . collect ( ) ;
140+
141+
142+ prefixes_of . iter ( )
143+ . map ( |prefix_of| {
144+ let prefix_of_index = fields . clone ( ) . into_iter ( ) . position ( |f| & f == prefix_of ) . unwrap ( ) ;
145+ match attr :: protocol ( & prefix_of . attrs ) . unwrap ( ) {
146+ attr :: Protocol :: LengthPrefix { kind , prefix_subfield_names , .. } => {
147+ ( prefix_of_index , kind . clone ( ) , prefix_subfield_names )
148+ }
149+ _ => unreachable ! ( ) ,
150+ }
151+ } ) . collect ( )
140152}
141153
142154fn write_named_fields ( fields_named : & syn:: FieldsNamed )
@@ -145,7 +157,7 @@ fn write_named_fields(fields_named: &syn::FieldsNamed)
145157 let field_name = & field. ident ;
146158 // This field may store the length prefix of another field.
147159 let update_hints = update_hints_after_write ( field, & fields_named. named ) ;
148- let update_hints_fixed = update_hints__fixed_after_read ( field, & fields_named. named ) ;
160+ let update_hints_fixed = update_hint_fixed_length ( field, & fields_named. named ) ;
149161
150162 quote ! {
151163 {
@@ -162,7 +174,7 @@ fn write_named_fields(fields_named: &syn::FieldsNamed)
162174}
163175
164176fn read_unnamed_fields ( fields_unnamed : & syn:: FieldsUnnamed )
165- -> TokenStream {
177+ -> TokenStream {
166178 let field_initializers: Vec < _ > = fields_unnamed. unnamed . iter ( ) . map ( |field| {
167179 let field_ty = & field. ty ;
168180
@@ -179,7 +191,7 @@ fn read_unnamed_fields(fields_unnamed: &syn::FieldsUnnamed)
179191}
180192
181193fn write_unnamed_fields ( fields_unnamed : & syn:: FieldsUnnamed )
182- -> TokenStream {
194+ -> TokenStream {
183195 let field_indices = ( 0 ..fields_unnamed. unnamed . len ( ) ) . into_iter ( ) . map ( syn:: Index :: from) ;
184196
185197 let field_writers: Vec < _ > = field_indices. map ( |field_index| {
0 commit comments