Skip to content

Commit 257ccfa

Browse files
authored
der_derive: remove synstructure dependency (#192)
Little of `synstructure`'s actual functionality is being used, and given all of the additional parsing work that needs to be done in the proc macro, we already have the relevant context that `synstructure` would abstract over. Removing `synstructure` also means we can start using the `proc-macro-error` crate to provide better error messages.
1 parent ed9070d commit 257ccfa

File tree

8 files changed

+236
-238
lines changed

8 files changed

+236
-238
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

der/derive/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,4 @@ proc-macro = true
1818
[dependencies]
1919
proc-macro2 = "1"
2020
quote = "1"
21-
syn = "1"
22-
synstructure = "0.12"
21+
syn = { version = "1", features = ["extra-traits"] }

der/derive/src/choice.rs

Lines changed: 50 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,19 @@
55
use crate::{FieldAttrs, TypeAttrs};
66
use proc_macro2::TokenStream;
77
use quote::{quote, ToTokens};
8-
use syn::{DataEnum, Lifetime, Variant};
9-
use synstructure::{Structure, VariantInfo};
8+
use syn::{Attribute, DataEnum, Fields, Ident, Lifetime, Variant};
109

1110
/// Derive the `Choice` trait for an enum.
1211
pub(crate) struct DeriveChoice {
12+
/// Name of the enum type.
13+
ident: Ident,
14+
1315
/// `asn1` attributes defined at the type level.
1416
type_attrs: TypeAttrs,
1517

18+
/// Lifetime of the type.
19+
lifetime: Option<Lifetime>,
20+
1621
/// Tags included in the impl body for `der::Choice`.
1722
choice_body: TokenStream,
1823

@@ -31,23 +36,24 @@ pub(crate) struct DeriveChoice {
3136

3237
impl DeriveChoice {
3338
/// 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 {
4145
let mut state = Self {
42-
type_attrs: TypeAttrs::parse(&s.ast().attrs),
46+
ident,
47+
type_attrs: TypeAttrs::parse(attrs),
48+
lifetime,
4349
choice_body: TokenStream::new(),
4450
decode_body: TokenStream::new(),
4551
encode_body: TokenStream::new(),
4652
encoded_len_body: TokenStream::new(),
4753
tagged_body: TokenStream::new(),
4854
};
4955

50-
for (variant_info, variant) in s.variants().iter().zip(&data.variants) {
56+
for variant in &data.variants {
5157
let field_attrs = FieldAttrs::parse(&variant.attrs);
5258
let tag = field_attrs.tag(&state.type_attrs).unwrap_or_else(|| {
5359
panic!(
@@ -59,21 +65,21 @@ impl DeriveChoice {
5965
state.derive_variant_choice(&tag);
6066
state.derive_variant_decoder(variant, &tag, &field_attrs);
6167

62-
match variant_info.bindings().len() {
68+
match &variant.fields {
6369
// 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);
6773
state.derive_variant_tagged(variant, &tag);
6874
}
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
7278
),
7379
}
7480
}
7581

76-
state.finish(s, lifetime)
82+
state.to_tokens()
7783
}
7884

7985
/// Derive the body of `Choice::can_decode
@@ -100,34 +106,17 @@ impl DeriveChoice {
100106
}
101107

102108
/// 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);
116114
}
117115

118116
/// 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(),) }
131120
.to_tokens(&mut self.encoded_len_body);
132121
}
133122

@@ -137,14 +126,21 @@ impl DeriveChoice {
137126
{ quote!(Self::#variant_ident(_) => #tag,) }.to_tokens(&mut self.tagged_body);
138127
}
139128

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),
144133
None => quote!('_),
145134
};
146135

136+
let lt_param = self
137+
.lifetime
138+
.as_ref()
139+
.map(|_| lifetime.clone())
140+
.unwrap_or_default();
141+
147142
let Self {
143+
ident,
148144
choice_body,
149145
decode_body,
150146
encode_body,
@@ -153,14 +149,14 @@ impl DeriveChoice {
153149
..
154150
} = self;
155151

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> {
158154
fn can_decode(tag: ::der::Tag) -> bool {
159155
matches!(tag, #choice_body)
160156
}
161157
}
162158

163-
gen impl ::der::Decodable<#lifetime> for @Self {
159+
impl<#lt_param> ::der::Decodable<#lifetime> for #ident<#lt_param> {
164160
fn decode(decoder: &mut ::der::Decoder<#lifetime>) -> ::der::Result<Self> {
165161
match decoder.peek_tag()? {
166162
#decode_body
@@ -173,7 +169,7 @@ impl DeriveChoice {
173169
}
174170
}
175171

176-
gen impl ::der::Encodable for @Self {
172+
impl<#lt_param> ::der::Encodable for #ident<#lt_param> {
177173
fn encode(&self, encoder: &mut ::der::Encoder<'_>) -> ::der::Result<()> {
178174
match self {
179175
#encode_body
@@ -187,13 +183,13 @@ impl DeriveChoice {
187183
}
188184
}
189185

190-
gen impl ::der::Tagged for @Self {
186+
impl<#lt_param> ::der::Tagged for #ident<#lt_param> {
191187
fn tag(&self) -> ::der::Tag {
192188
match self {
193189
#tagged_body
194190
}
195191
}
196192
}
197-
})
193+
}
198194
}
199195
}

der/derive/src/enumerated.rs

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55
use crate::ATTR_NAME;
66
use proc_macro2::TokenStream;
77
use quote::{quote, ToTokens};
8-
use syn::{DataEnum, Expr, ExprLit, Ident, Lit, LitInt};
9-
use synstructure::Structure;
8+
use syn::{Attribute, DataEnum, Expr, ExprLit, Ident, Lit, LitInt};
109

1110
/// Valid options for the `#[repr]` attribute on `Enumerated` types.
1211
const REPR_TYPES: &[&str] = &["u8", "u16", "u32"];
1312

1413
/// Derive the `Enumerated` trait for an enum.
1514
pub(crate) struct DeriveEnumerated {
15+
/// Name of the enum type.
16+
ident: Ident,
17+
1618
/// Value of the `repr` attribute.
1719
repr: Ident,
1820

@@ -22,16 +24,10 @@ pub(crate) struct DeriveEnumerated {
2224

2325
impl DeriveEnumerated {
2426
/// Derive `Decodable` on an enum.
25-
pub fn derive(s: Structure<'_>, data: &DataEnum) -> TokenStream {
26-
assert_eq!(
27-
s.variants().len(),
28-
data.variants.len(),
29-
"enum variant count mismatch"
30-
);
31-
27+
pub fn derive(ident: Ident, data: DataEnum, attrs: &[Attribute]) -> TokenStream {
3228
// Reject `asn1` attributes, parse the `repr` attribute
3329
let mut repr: Option<Ident> = None;
34-
for attr in &s.ast().attrs {
30+
for attr in attrs {
3531
if attr.path.is_ident(ATTR_NAME) {
3632
panic!("`asn1` attribute is not allowed on `Enumerated` types");
3733
} else if attr.path.is_ident("repr") {
@@ -78,6 +74,7 @@ impl DeriveEnumerated {
7874
}
7975

8076
Self {
77+
ident,
8178
repr: repr.unwrap_or_else(|| {
8279
panic!(
8380
"no `#[repr]` attribute on enum: must be one of {:?}",
@@ -86,20 +83,20 @@ impl DeriveEnumerated {
8683
}),
8784
variants,
8885
}
89-
.finish(s)
86+
.to_tokens()
9087
}
9188

92-
/// Finish deriving an enum
93-
fn finish(self, s: Structure<'_>) -> TokenStream {
94-
let repr = self.repr;
95-
89+
/// Lower the derived output into a [`TokenStream`].
90+
fn to_tokens(&self) -> TokenStream {
9691
let mut try_from_body = TokenStream::new();
9792
for (ident, discriminant) in &self.variants {
9893
{ quote!(#discriminant => Ok(Self::#ident),) }.to_tokens(&mut try_from_body);
9994
}
10095

101-
s.gen_impl(quote! {
102-
gen impl ::der::DecodeValue<'static> for @Self {
96+
let Self { ident, repr, .. } = self;
97+
98+
quote! {
99+
impl ::der::DecodeValue<'static> for #ident {
103100
fn decode_value(
104101
decoder: &mut ::der::Decoder<'_>,
105102
length: ::der::Length
@@ -108,7 +105,7 @@ impl DeriveEnumerated {
108105
}
109106
}
110107

111-
gen impl ::der::EncodeValue for @Self {
108+
impl ::der::EncodeValue for #ident {
112109
fn value_len(&self) -> ::der::Result<::der::Length> {
113110
::der::EncodeValue::value_len(&(*self as #repr))
114111
}
@@ -118,11 +115,11 @@ impl DeriveEnumerated {
118115
}
119116
}
120117

121-
gen impl ::der::FixedTag for @Self {
118+
impl ::der::FixedTag for #ident {
122119
const TAG: ::der::Tag = ::der::Tag::Enumerated;
123120
}
124121

125-
gen impl TryFrom<#repr> for @Self {
122+
impl TryFrom<#repr> for #ident {
126123
type Error = ::der::Error;
127124

128125
fn try_from(n: #repr) -> ::der::Result<Self> {
@@ -132,6 +129,6 @@ impl DeriveEnumerated {
132129
}
133130
}
134131
}
135-
})
132+
}
136133
}
137134
}

0 commit comments

Comments
 (0)