5
5
use crate :: { FieldAttrs , TypeAttrs } ;
6
6
use proc_macro2:: TokenStream ;
7
7
use quote:: { quote, ToTokens } ;
8
- use syn:: { DataEnum , Lifetime , Variant } ;
9
- use synstructure:: { Structure , VariantInfo } ;
8
+ use syn:: { Attribute , DataEnum , Fields , Ident , Lifetime , Variant } ;
10
9
11
10
/// Derive the `Choice` trait for an enum.
12
11
pub ( crate ) struct DeriveChoice {
12
+ /// Name of the enum type.
13
+ ident : Ident ,
14
+
13
15
/// `asn1` attributes defined at the type level.
14
16
type_attrs : TypeAttrs ,
15
17
18
+ /// Lifetime of the type.
19
+ lifetime : Option < Lifetime > ,
20
+
16
21
/// Tags included in the impl body for `der::Choice`.
17
22
choice_body : TokenStream ,
18
23
@@ -31,23 +36,24 @@ pub(crate) struct DeriveChoice {
31
36
32
37
impl DeriveChoice {
33
38
/// Derive `Decodable` on an enum.
34
- pub fn derive ( s : Structure < ' _ > , data : & DataEnum , lifetime : Option < & Lifetime > ) -> TokenStream {
35
- assert_eq ! (
36
- s. variants( ) . len( ) ,
37
- data. variants. len( ) ,
38
- "enum variant count mismatch"
39
- ) ;
40
-
39
+ pub fn derive (
40
+ ident : Ident ,
41
+ data : DataEnum ,
42
+ attrs : & [ Attribute ] ,
43
+ lifetime : Option < Lifetime > ,
44
+ ) -> TokenStream {
41
45
let mut state = Self {
42
- type_attrs : TypeAttrs :: parse ( & s. ast ( ) . attrs ) ,
46
+ ident,
47
+ type_attrs : TypeAttrs :: parse ( attrs) ,
48
+ lifetime,
43
49
choice_body : TokenStream :: new ( ) ,
44
50
decode_body : TokenStream :: new ( ) ,
45
51
encode_body : TokenStream :: new ( ) ,
46
52
encoded_len_body : TokenStream :: new ( ) ,
47
53
tagged_body : TokenStream :: new ( ) ,
48
54
} ;
49
55
50
- for ( variant_info , variant) in s . variants ( ) . iter ( ) . zip ( & data. variants ) {
56
+ for variant in & data. variants {
51
57
let field_attrs = FieldAttrs :: parse ( & variant. attrs ) ;
52
58
let tag = field_attrs. tag ( & state. type_attrs ) . unwrap_or_else ( || {
53
59
panic ! (
@@ -59,21 +65,21 @@ impl DeriveChoice {
59
65
state. derive_variant_choice ( & tag) ;
60
66
state. derive_variant_decoder ( variant, & tag, & field_attrs) ;
61
67
62
- match variant_info . bindings ( ) . len ( ) {
68
+ match & variant . fields {
63
69
// TODO(tarcieri): handle 0 bindings for ASN.1 NULL
64
- 1 => {
65
- state. derive_variant_encoder ( variant_info , & field_attrs) ;
66
- state. derive_variant_encoded_len ( variant_info ) ;
70
+ Fields :: Unnamed ( fields ) if fields . unnamed . len ( ) == 1 => {
71
+ state. derive_variant_encoder ( variant , & field_attrs) ;
72
+ state. derive_variant_encoded_len ( variant ) ;
67
73
state. derive_variant_tagged ( variant, & tag) ;
68
74
}
69
- other => panic ! (
70
- "unsupported number of ASN.1 variant bindings for {}: {} " ,
71
- & variant. ident, other
75
+ _ => panic ! (
76
+ "enum variant `{}` must be a 1-element tuple struct " ,
77
+ & variant. ident
72
78
) ,
73
79
}
74
80
}
75
81
76
- state. finish ( s , lifetime )
82
+ state. to_tokens ( )
77
83
}
78
84
79
85
/// Derive the body of `Choice::can_decode
@@ -100,34 +106,17 @@ impl DeriveChoice {
100
106
}
101
107
102
108
/// Derive a match arm for the impl body for `der::Encodable::encode`.
103
- fn derive_variant_encoder ( & mut self , variant : & VariantInfo < ' _ > , field_attrs : & FieldAttrs ) {
104
- assert_eq ! (
105
- variant. bindings( ) . len( ) ,
106
- 1 ,
107
- "unexpected number of variant bindings"
108
- ) ;
109
-
110
- variant
111
- . each ( |bi| {
112
- let binding = & bi. binding ;
113
- field_attrs. encoder ( & quote ! ( #binding) , & self . type_attrs )
114
- } )
115
- . to_tokens ( & mut self . encode_body ) ;
109
+ fn derive_variant_encoder ( & mut self , variant : & Variant , field_attrs : & FieldAttrs ) {
110
+ let variant_ident = & variant. ident ;
111
+ let binding = quote ! ( variant) ;
112
+ let encoder = field_attrs. encoder ( & binding, & self . type_attrs ) ;
113
+ { quote ! ( Self :: #variant_ident( #binding) => #encoder, ) } . to_tokens ( & mut self . encode_body ) ;
116
114
}
117
115
118
116
/// Derive a match arm for the impl body for `der::Encodable::encode`.
119
- fn derive_variant_encoded_len ( & mut self , variant : & VariantInfo < ' _ > ) {
120
- assert_eq ! (
121
- variant. bindings( ) . len( ) ,
122
- 1 ,
123
- "unexpected number of variant bindings"
124
- ) ;
125
-
126
- variant
127
- . each ( |bi| {
128
- let binding = & bi. binding ;
129
- quote ! ( #binding. encoded_len( ) )
130
- } )
117
+ fn derive_variant_encoded_len ( & mut self , variant : & Variant ) {
118
+ let variant_ident = & variant. ident ;
119
+ { quote ! ( Self :: #variant_ident( variant) => variant. encoded_len( ) , ) }
131
120
. to_tokens ( & mut self . encoded_len_body ) ;
132
121
}
133
122
@@ -137,14 +126,21 @@ impl DeriveChoice {
137
126
{ quote ! ( Self :: #variant_ident( _) => #tag, ) } . to_tokens ( & mut self . tagged_body ) ;
138
127
}
139
128
140
- /// Finish deriving an enum
141
- fn finish ( self , s : Structure < ' _ > , lifetime : Option < & Lifetime > ) -> TokenStream {
142
- let lifetime = match lifetime {
143
- Some ( lifetime) => quote ! ( #lifetime) ,
129
+ /// Lower the derived output into a [`TokenStream`].
130
+ fn to_tokens ( & self ) -> TokenStream {
131
+ let lifetime = match self . lifetime {
132
+ Some ( ref lifetime) => quote ! ( #lifetime) ,
144
133
None => quote ! ( ' _) ,
145
134
} ;
146
135
136
+ let lt_param = self
137
+ . lifetime
138
+ . as_ref ( )
139
+ . map ( |_| lifetime. clone ( ) )
140
+ . unwrap_or_default ( ) ;
141
+
147
142
let Self {
143
+ ident,
148
144
choice_body,
149
145
decode_body,
150
146
encode_body,
@@ -153,14 +149,14 @@ impl DeriveChoice {
153
149
..
154
150
} = self ;
155
151
156
- s . gen_impl ( quote ! {
157
- gen impl :: der:: Choice <#lifetime> for @ Self {
152
+ quote ! {
153
+ impl <#lt_param> :: der:: Choice <#lifetime> for #ident<#lt_param> {
158
154
fn can_decode( tag: :: der:: Tag ) -> bool {
159
155
matches!( tag, #choice_body)
160
156
}
161
157
}
162
158
163
- gen impl :: der:: Decodable <#lifetime> for @ Self {
159
+ impl <#lt_param> :: der:: Decodable <#lifetime> for #ident<#lt_param> {
164
160
fn decode( decoder: & mut :: der:: Decoder <#lifetime>) -> :: der:: Result <Self > {
165
161
match decoder. peek_tag( ) ? {
166
162
#decode_body
@@ -173,7 +169,7 @@ impl DeriveChoice {
173
169
}
174
170
}
175
171
176
- gen impl :: der:: Encodable for @ Self {
172
+ impl <#lt_param> :: der:: Encodable for #ident<#lt_param> {
177
173
fn encode( & self , encoder: & mut :: der:: Encoder <' _>) -> :: der:: Result <( ) > {
178
174
match self {
179
175
#encode_body
@@ -187,13 +183,13 @@ impl DeriveChoice {
187
183
}
188
184
}
189
185
190
- gen impl :: der:: Tagged for @ Self {
186
+ impl <#lt_param> :: der:: Tagged for #ident<#lt_param> {
191
187
fn tag( & self ) -> :: der:: Tag {
192
188
match self {
193
189
#tagged_body
194
190
}
195
191
}
196
192
}
197
- } )
193
+ }
198
194
}
199
195
}
0 commit comments