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
extern crate proc_macro; use proc_macro::{ TokenStream, }; use quote::quote; use syn::{self, DeriveInput, TypeTuple}; #[proc_macro_attribute] pub fn err_gen(attr: TokenStream, input: TokenStream) -> TokenStream { use syn::Data::*; let attr_ast: TypeTuple = syn::parse(attr).unwrap(); let input_ast: DeriveInput = syn::parse(input).unwrap(); let raw_enum = match input_ast.data { Enum(data_enum) => data_enum, _ => panic!("input must be an enum"), }; let name = &input_ast.ident; let mut nested_variants = quote! {}; for variant in raw_enum.variants.iter() { let ident = &variant.ident; nested_variants = match variant.attrs.get(0usize) { Some(attr) => quote! { #attr #ident, #nested_variants }, None => quote! { #ident, #nested_variants }, }; }; let enum_declaration = quote! { #[derive(Display, Debug)] pub enum #name { #nested_variants ErrorNode(Box<dyn std::error::Error>), } }; let mut impl_clauses = quote! {}; for element in attr_ast.elems.iter() { impl_clauses = quote! { impl From<#element> for #name { fn from(e: #element) -> Self { Self::ErrorNode(Box::new(e)) } } #impl_clauses }; }; let result = quote! { #enum_declaration #impl_clauses }; result.into() }