Skip to content

Commit 16fb786

Browse files
authored
der-derive: adds generics support for ValueOrd and Choice (RustCrypto#1402)
1 parent cde2991 commit 16fb786

File tree

2 files changed

+37
-51
lines changed

2 files changed

+37
-51
lines changed

der/derive/src/choice.rs

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ use self::variant::ChoiceVariant;
88
use crate::{default_lifetime, TypeAttrs};
99
use proc_macro2::TokenStream;
1010
use quote::quote;
11-
use syn::{DeriveInput, Ident, Lifetime};
11+
use syn::{DeriveInput, GenericParam, Generics, Ident, LifetimeParam};
1212

1313
/// Derive the `Choice` trait for an enum.
1414
pub(crate) struct DeriveChoice {
1515
/// Name of the enum type.
1616
ident: Ident,
1717

18-
/// Lifetime of the type.
19-
lifetime: Option<Lifetime>,
18+
/// Generics of the enum.
19+
generics: Generics,
2020

2121
/// Variants of this `Choice`.
2222
variants: Vec<ChoiceVariant>,
@@ -33,13 +33,6 @@ impl DeriveChoice {
3333
),
3434
};
3535

36-
// TODO(tarcieri): properly handle multiple lifetimes
37-
let lifetime = input
38-
.generics
39-
.lifetimes()
40-
.next()
41-
.map(|lt| lt.lifetime.clone());
42-
4336
let type_attrs = TypeAttrs::parse(&input.attrs)?;
4437
let variants = data
4538
.variants
@@ -49,30 +42,33 @@ impl DeriveChoice {
4942

5043
Ok(Self {
5144
ident: input.ident,
52-
lifetime,
45+
generics: input.generics.clone(),
5346
variants,
5447
})
5548
}
5649

5750
/// Lower the derived output into a [`TokenStream`].
5851
pub fn to_tokens(&self) -> TokenStream {
5952
let ident = &self.ident;
53+
let mut generics = self.generics.clone();
6054

61-
let lifetime = match self.lifetime {
62-
Some(ref lifetime) => quote!(#lifetime),
63-
None => {
64-
let lifetime = default_lifetime();
65-
quote!(#lifetime)
66-
}
67-
};
68-
69-
// Lifetime parameters
70-
// TODO(tarcieri): support multiple lifetimes
71-
let lt_params = self
72-
.lifetime
73-
.as_ref()
74-
.map(|_| lifetime.clone())
75-
.unwrap_or_default();
55+
// Use the first lifetime parameter as lifetime for Decode/Encode lifetime
56+
// if none found, add one.
57+
let lifetime = generics
58+
.lifetimes()
59+
.next()
60+
.map(|lt| lt.lifetime.clone())
61+
.unwrap_or_else(|| {
62+
let lt = default_lifetime();
63+
generics
64+
.params
65+
.insert(0, GenericParam::Lifetime(LifetimeParam::new(lt.clone())));
66+
lt
67+
});
68+
69+
// We may or may not have inserted a lifetime.
70+
let (_, ty_generics, where_clause) = self.generics.split_for_impl();
71+
let (impl_generics, _, _) = generics.split_for_impl();
7672

7773
let mut can_decode_body = Vec::new();
7874
let mut decode_body = Vec::new();
@@ -89,13 +85,13 @@ impl DeriveChoice {
8985
}
9086

9187
quote! {
92-
impl<#lifetime> ::der::Choice<#lifetime> for #ident<#lt_params> {
88+
impl #impl_generics ::der::Choice<#lifetime> for #ident #ty_generics #where_clause {
9389
fn can_decode(tag: ::der::Tag) -> bool {
9490
matches!(tag, #(#can_decode_body)|*)
9591
}
9692
}
9793

98-
impl<#lifetime> ::der::Decode<#lifetime> for #ident<#lt_params> {
94+
impl #impl_generics ::der::Decode<#lifetime> for #ident #ty_generics #where_clause {
9995
type Error = ::der::Error;
10096

10197
fn decode<R: ::der::Reader<#lifetime>>(reader: &mut R) -> ::der::Result<Self> {
@@ -111,7 +107,7 @@ impl DeriveChoice {
111107
}
112108
}
113109

114-
impl<#lt_params> ::der::EncodeValue for #ident<#lt_params> {
110+
impl #impl_generics ::der::EncodeValue for #ident #ty_generics #where_clause {
115111
fn encode_value(&self, encoder: &mut impl ::der::Writer) -> ::der::Result<()> {
116112
match self {
117113
#(#encode_body)*
@@ -125,7 +121,7 @@ impl DeriveChoice {
125121
}
126122
}
127123

128-
impl<#lt_params> ::der::Tagged for #ident<#lt_params> {
124+
impl #impl_generics ::der::Tagged for #ident #ty_generics #where_clause {
129125
fn tag(&self) -> ::der::Tag {
130126
match self {
131127
#(#tagged_body)*
@@ -165,7 +161,7 @@ mod tests {
165161

166162
let ir = DeriveChoice::new(input).unwrap();
167163
assert_eq!(ir.ident, "Time");
168-
assert_eq!(ir.lifetime, None);
164+
assert_eq!(ir.generics.lifetimes().next(), None);
169165
assert_eq!(ir.variants.len(), 2);
170166

171167
let utc_time = &ir.variants[0];
@@ -205,7 +201,10 @@ mod tests {
205201

206202
let ir = DeriveChoice::new(input).unwrap();
207203
assert_eq!(ir.ident, "ImplicitChoice");
208-
assert_eq!(ir.lifetime.unwrap().to_string(), "'a");
204+
assert_eq!(
205+
ir.generics.lifetimes().next().unwrap().lifetime.to_string(),
206+
"'a"
207+
);
209208
assert_eq!(ir.variants.len(), 3);
210209

211210
let bit_string = &ir.variants[0];

der/derive/src/value_ord.rs

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
use crate::{FieldAttrs, TypeAttrs};
99
use proc_macro2::TokenStream;
1010
use quote::quote;
11-
use syn::{DeriveInput, Field, Ident, Lifetime, Variant};
11+
use syn::{DeriveInput, Field, Generics, Ident, Variant};
1212

1313
/// Derive the `Enumerated` trait for an enum.
1414
pub(crate) struct DeriveValueOrd {
1515
/// Name of the enum.
1616
ident: Ident,
1717

18-
/// Lifetime of the struct.
19-
lifetime: Option<Lifetime>,
18+
/// Generics of the enum.
19+
generics: Generics,
2020

2121
/// Fields of structs or enum variants.
2222
fields: Vec<ValueField>,
@@ -31,13 +31,6 @@ impl DeriveValueOrd {
3131
let ident = input.ident;
3232
let type_attrs = TypeAttrs::parse(&input.attrs)?;
3333

34-
// TODO(tarcieri): properly handle multiple lifetimes
35-
let lifetime = input
36-
.generics
37-
.lifetimes()
38-
.next()
39-
.map(|lt| lt.lifetime.clone());
40-
4134
let (fields, input_type) = match input.data {
4235
syn::Data::Enum(data) => (
4336
data.variants
@@ -62,7 +55,7 @@ impl DeriveValueOrd {
6255

6356
Ok(Self {
6457
ident,
65-
lifetime,
58+
generics: input.generics.clone(),
6659
fields,
6760
input_type,
6861
})
@@ -72,13 +65,7 @@ impl DeriveValueOrd {
7265
pub fn to_tokens(&self) -> TokenStream {
7366
let ident = &self.ident;
7467

75-
// Lifetime parameters
76-
// TODO(tarcieri): support multiple lifetimes
77-
let lt_params = self
78-
.lifetime
79-
.as_ref()
80-
.map(|lt| vec![lt.clone()])
81-
.unwrap_or_default();
68+
let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();
8269

8370
let mut body = Vec::new();
8471

@@ -110,7 +97,7 @@ impl DeriveValueOrd {
11097
};
11198

11299
quote! {
113-
impl<#(#lt_params)*> ::der::ValueOrd for #ident<#(#lt_params)*> {
100+
impl #impl_generics ::der::ValueOrd for #ident #ty_generics #where_clause {
114101
fn value_cmp(&self, other: &Self) -> ::der::Result<::core::cmp::Ordering> {
115102
#body
116103
}

0 commit comments

Comments
 (0)