1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
From f9b8d46c4588ea0d60ba04ba2447cbae695ad67e Mon Sep 17 00:00:00 2001
From: "Chris West (Faux)" <git@goeswhere.com>
Date: Sun, 16 Jun 2019 16:09:46 +0100
Subject: [PATCH 2/2] upgrade syn/quote
---
Cargo.toml | 4 ++--
src/lib.rs | 35 ++++++++++++++---------------------
2 files changed, 16 insertions(+), 23 deletions(-)
diff --git a/src/lib.rs b/src/lib.rs
index 3a1fcc6..3b5c0d4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -89,6 +89,7 @@ extern crate proc_macro;
extern crate num_traits;
#[macro_use]
extern crate quote;
+#[macro_use]
extern crate syn;
use proc_macro::TokenStream;
@@ -97,43 +98,35 @@ use proc_macro::TokenStream;
/// `num_traits::FromPrimitive`
#[proc_macro_derive(Primitive)]
pub fn primitive(input: TokenStream) -> TokenStream {
- // Construct a string representation of the type definition
- let s = input.to_string();
-
- // Parse the string representation
- let ast = syn::parse_derive_input(&s).unwrap();
-
- // Build the impl
- let gen = impl_primitive(&ast);
-
- // Return the generated impl
- gen.parse().unwrap()
+ let ast = parse_macro_input!(input as syn::DeriveInput);
+ impl_primitive(&ast)
}
-fn impl_primitive(ast: &syn::DeriveInput) -> quote::Tokens {
+fn impl_primitive(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
// Check if derive(Primitive) was specified for a struct
- if let syn::Body::Enum(ref variant) = ast.body {
+ if let syn::Data::Enum(ref variant) = ast.data {
- let (var_u64, dis_u64): (Vec<_>, Vec<_>) = variant.iter().map(|v| {
- if v.data != syn::VariantData::Unit {
- panic!("#[derive(Primitive) can only operate on C-like enums");
+ let (var_u64, dis_u64): (Vec<_>, Vec<_>) = variant.variants.iter().map(|v| {
+ match v.fields {
+ syn::Fields::Unit => (),
+ _ => panic!("#[derive(Primitive) can only operate on C-like enums"),
}
if v.discriminant.is_none() {
panic!("#[derive(Primitive) requires C-like enums with \
discriminants for all enum variants");
}
- let discrim = match v.discriminant.clone().unwrap() {
- syn::ConstExpr::Cast(real, _) => *real,
+ let discrim = match v.discriminant.clone().map(|(_eq, expr)| expr).unwrap() {
+ syn::Expr::Cast(real) => *real.expr,
orig => orig,
};
(v.ident.clone(), discrim)
}).unzip();
// quote!{} needs this to be a vec since its in #( )*
- let enum_u64 = vec![name.clone(); variant.len()];
+ let enum_u64 = vec![name.clone(); variant.variants.len()];
// can't reuse variables in quote!{} body
let var_i64 = var_u64.clone();
@@ -149,7 +142,7 @@ fn impl_primitive(ast: &syn::DeriveInput) -> quote::Tokens {
let to_var_i64 = var_u64.clone();
let to_dis_i64 = dis_u64.clone();
- quote! {
+ TokenStream::from(quote! {
impl ::num_traits::FromPrimitive for #name {
fn from_u64(val: u64) -> Option<Self> {
match val as _ {
@@ -179,7 +172,7 @@ fn impl_primitive(ast: &syn::DeriveInput) -> quote::Tokens {
}
}
}
- }
+ })
} else {
panic!("#[derive(Primitive)] is only valid for C-like enums");
}
--
2.24.1
|