1
- pub mod enums;
2
-
3
- use crate :: attr;
4
1
use proc_macro2:: TokenStream ;
5
2
use syn;
3
+ use syn:: Field ;
4
+
5
+ use crate :: attr;
6
+
7
+ pub mod enums;
6
8
7
9
pub fn read_fields ( fields : & syn:: Fields )
8
- -> TokenStream {
10
+ -> TokenStream {
9
11
match * fields {
10
12
syn:: Fields :: Named ( ref fields_named) => read_named_fields ( fields_named) ,
11
13
syn:: Fields :: Unnamed ( ref fields_unnamed) => read_unnamed_fields ( fields_unnamed) ,
@@ -14,7 +16,7 @@ pub fn read_fields(fields: &syn::Fields)
14
16
}
15
17
16
18
pub fn write_fields ( fields : & syn:: Fields )
17
- -> TokenStream {
19
+ -> TokenStream {
18
20
match * fields {
19
21
syn:: Fields :: Named ( ref fields_named) => write_named_fields ( fields_named) ,
20
22
syn:: Fields :: Unnamed ( ref fields_unnamed) => write_unnamed_fields ( fields_unnamed) ,
@@ -32,9 +34,9 @@ fn read_named_fields(fields_named: &syn::FieldsNamed)
32
34
let field_initializers: Vec < _ > = fields_named. named . iter ( ) . map ( |field| {
33
35
let field_name = & field. ident ;
34
36
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.
36
38
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 ) ;
38
40
39
41
quote ! {
40
42
#field_name : {
@@ -53,26 +55,30 @@ fn read_named_fields(fields_named: &syn::FieldsNamed)
53
55
fn update_hints_after_read < ' a > ( field : & ' a syn:: Field ,
54
56
fields : impl IntoIterator < Item =& ' a syn:: Field > + Clone )
55
57
-> 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 ) | {
57
59
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 > > ( ) ;
58
66
67
+ if hint_setters. is_empty ( ) {
68
+ quote ! { }
69
+ } else {
59
70
quote ! {
60
71
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) ; *
64
73
}
65
74
}
66
- } else {
67
- quote ! { }
68
75
}
69
76
}
70
77
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 ) {
76
82
let position = fields. clone ( ) . into_iter ( ) . position ( |f| f == field) . unwrap ( ) ;
77
83
78
84
quote ! {
@@ -85,20 +91,26 @@ fn update_hints__fixed_after_read<'a>(field: &'a syn::Field,
85
91
86
92
fn update_hints_after_write < ' a > ( field : & ' a syn:: Field ,
87
93
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 ) | {
90
96
let field_name = & field. ident ;
91
97
let kind = kind. path_expr ( ) ;
92
98
93
99
quote ! {
94
- if let Ok ( ( ) ) = res {
95
100
__hints. set_field_length( #length_prefix_of,
96
101
( self . #field_name #( . #prefix_subfield_names) * ) . clone( ) as usize ,
97
102
#kind) ;
98
- }
99
103
}
104
+ } ) . collect :: < Vec < TokenStream > > ( ) ;
105
+
106
+ if hint_setters. is_empty ( ) {
107
+ quote ! { }
100
108
} else {
101
- quote ! { }
109
+ quote ! {
110
+ if let Ok ( ( ) ) = res {
111
+ #( #hint_setters) ; *
112
+ }
113
+ }
102
114
}
103
115
}
104
116
@@ -110,33 +122,33 @@ fn update_hints_after_write<'a>(field: &'a syn::Field,
110
122
/// Returns the field index of the field whose length is specified.
111
123
fn length_prefix_of < ' a > ( field : & ' a syn:: Field ,
112
124
fields : impl IntoIterator < Item =& ' a syn:: Field > + Clone )
113
- -> Option < ( usize , attr:: LengthPrefixKind , Vec < syn:: Ident > ) > {
125
+ -> Vec < ( usize , attr:: LengthPrefixKind , Vec < syn:: Ident > ) > {
114
126
let potential_prefix = field. ident . as_ref ( ) ;
115
127
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| {
117
129
match attr:: protocol ( & potential_prefix_of. attrs ) {
118
130
Some ( attr:: Protocol :: LengthPrefix { ref prefix_field_name, .. } ) => {
119
131
if !fields. clone ( ) . into_iter ( ) . any ( |f| f. ident . as_ref ( ) == Some ( prefix_field_name) ) {
120
132
panic ! ( "length prefix is invalid: there is no sibling field named '{}" , prefix_field_name) ;
121
133
}
122
134
123
135
potential_prefix == Some ( prefix_field_name)
124
- } ,
136
+ }
125
137
_ => false ,
126
138
}
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 ( )
140
152
}
141
153
142
154
fn write_named_fields ( fields_named : & syn:: FieldsNamed )
@@ -145,7 +157,7 @@ fn write_named_fields(fields_named: &syn::FieldsNamed)
145
157
let field_name = & field. ident ;
146
158
// This field may store the length prefix of another field.
147
159
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 ) ;
149
161
150
162
quote ! {
151
163
{
@@ -162,7 +174,7 @@ fn write_named_fields(fields_named: &syn::FieldsNamed)
162
174
}
163
175
164
176
fn read_unnamed_fields ( fields_unnamed : & syn:: FieldsUnnamed )
165
- -> TokenStream {
177
+ -> TokenStream {
166
178
let field_initializers: Vec < _ > = fields_unnamed. unnamed . iter ( ) . map ( |field| {
167
179
let field_ty = & field. ty ;
168
180
@@ -179,7 +191,7 @@ fn read_unnamed_fields(fields_unnamed: &syn::FieldsUnnamed)
179
191
}
180
192
181
193
fn write_unnamed_fields ( fields_unnamed : & syn:: FieldsUnnamed )
182
- -> TokenStream {
194
+ -> TokenStream {
183
195
let field_indices = ( 0 ..fields_unnamed. unnamed . len ( ) ) . into_iter ( ) . map ( syn:: Index :: from) ;
184
196
185
197
let field_writers: Vec < _ > = field_indices. map ( |field_index| {
0 commit comments