tpfs_log_event_procmacro/
lib.rs1#![forbid(unsafe_code)]
2#![recursion_limit = "128"]
3
4extern crate proc_macro;
5extern crate serde_derive;
6
7use quote::ToTokens;
8
9use proc_macro::TokenStream;
10use quote::quote;
11use syn::{Data, DataEnum, DeriveInput, Fields};
12
13#[proc_macro_attribute]
17pub fn logging_event(_args: TokenStream, input: TokenStream) -> TokenStream {
18 let ast: DeriveInput = syn::parse(input).unwrap();
19
20 let data: DataEnum = match ast.data {
22 Data::Enum(d) => d,
23 _ => panic!("LoggingEvent can only be derived for enums"),
24 };
25
26 let name = ast.ident;
27
28 let variant_tokens_streams = data.variants.iter().map(|v| {
29 let var_id = &v.ident;
30 let stringified = var_id.to_string();
31
32 let fields = v.fields.clone().into_token_stream();
33 let struct_tokens = match &v.fields {
35 Fields::Unnamed(fields) => {
36 let fields = fields.unnamed.iter().map(|f| {
37 let f_ty = &f.ty;
38 quote! {
39 pub #f_ty
40 }
41 });
42 quote! {
43 #[derive(::serde_derive::Serialize, Clone, Debug)]
44 pub struct #var_id(#(#fields),*);
45 }
46 }
47 Fields::Named(fields) => {
48 let fields = fields.named.iter().map(|f| {
49 let f_id = f.ident.as_ref().unwrap();
50 let f_ty = &f.ty;
51 quote! {
52 pub #f_id: #f_ty
53 }
54 });
55 quote! {
56 #[derive(::serde_derive::Serialize, Clone, Debug)]
57 pub struct #var_id {
58 #(#fields),*
59 }
60 }
61 }
62 _ => {
63 quote! {
64 #[derive(::serde_derive::Serialize, Clone, Debug)]
65 pub struct #var_id #fields;
66 }
67 }
68 };
69 let impl_tokens = quote! {
71 impl ::tpfs_logger_port::LogKVPairName for #var_id {
72 fn name(&self) -> &'static str {
73 #stringified
74 }
75 }
76
77 impl ::tpfs_logger_port::LogKVPairValue for #var_id {
78 type T = Self;
79
80 fn value(&self) -> Self::T {
81 self.clone() }
83 }
84 };
85 quote! {
86 #struct_tokens
87 #impl_tokens
88 }
89 });
90
91 let gen = quote! {
93 #[allow(non_snake_case)]
94 pub mod #name {
95 use super::*;
96 #(#variant_tokens_streams)*
97 }
98 };
99 gen.into()
100}