open_metrics_client_derive_text_encode/
lib.rs1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use proc_macro2::TokenStream as TokenStream2;
5use quote::quote;
6use syn::DeriveInput;
7
8#[proc_macro_derive(Encode)]
9pub fn derive_encode(input: TokenStream) -> TokenStream {
10 let ast: DeriveInput = syn::parse(input).unwrap();
11 let name = &ast.ident;
12
13 let body = match ast.data {
14 syn::Data::Struct(s) => match s.fields {
15 syn::Fields::Named(syn::FieldsNamed { named, .. }) => named
16 .into_iter()
17 .enumerate()
18 .map(|(i, f)| {
19 let ident = f.ident.unwrap();
20 let ident_string = KEYWORD_IDENTIFIERS
21 .iter()
22 .find(|pair| ident == pair.1)
23 .map(|pair| pair.0.to_string())
24 .unwrap_or_else(|| ident.to_string());
25
26 let maybe_comma = if i == 0 {
27 TokenStream2::default()
28 } else {
29 quote! { writer.write_all(b",")?; }
30 };
31 quote! {
32 #maybe_comma
33 writer.write_all(concat!(#ident_string, "=\"").as_bytes())?;
34 open_metrics_client::encoding::text::Encode::encode(&self.#ident, writer)?;
35 writer.write_all(b"\"")?;
36 }
37 })
38 .collect(),
39 syn::Fields::Unnamed(_) => {
40 panic!("Can not derive Encode for struct with unnamed fields.")
41 }
42 syn::Fields::Unit => panic!("Can not derive Encode for struct with unit field."),
43 },
44 syn::Data::Enum(syn::DataEnum { variants, .. }) => {
45 let match_arms: TokenStream2 = variants
46 .into_iter()
47 .map(|v| {
48 let ident = v.ident;
49 quote! {
50 #name::#ident => writer.write_all(stringify!(#ident).as_bytes())?,
51 }
52 })
53 .collect();
54
55 quote! {
56 match self {
57 #match_arms
58 }
59 }
60 }
61 syn::Data::Union(_) => panic!("Can not derive Encode for union."),
62 };
63
64 let gen = quote! {
65 impl open_metrics_client::encoding::text::Encode for #name {
66 fn encode(&self, writer: &mut dyn std::io::Write) -> std::result::Result<(), std::io::Error> {
67 #body
68
69 Ok(())
70 }
71 }
72 };
73 gen.into()
74}
75
76static KEYWORD_IDENTIFIERS: [(&str, &str); 48] = [
79 ("as", "r#as"),
80 ("break", "r#break"),
81 ("const", "r#const"),
82 ("continue", "r#continue"),
83 ("crate", "r#crate"),
84 ("else", "r#else"),
85 ("enum", "r#enum"),
86 ("extern", "r#extern"),
87 ("false", "r#false"),
88 ("fn", "r#fn"),
89 ("for", "r#for"),
90 ("if", "r#if"),
91 ("impl", "r#impl"),
92 ("in", "r#in"),
93 ("let", "r#let"),
94 ("loop", "r#loop"),
95 ("match", "r#match"),
96 ("mod", "r#mod"),
97 ("move", "r#move"),
98 ("mut", "r#mut"),
99 ("pub", "r#pub"),
100 ("ref", "r#ref"),
101 ("return", "r#return"),
102 ("static", "r#static"),
103 ("struct", "r#struct"),
104 ("trait", "r#trait"),
105 ("true", "r#true"),
106 ("type", "r#type"),
107 ("unsafe", "r#unsafe"),
108 ("use", "r#use"),
109 ("where", "r#where"),
110 ("while", "r#while"),
111 ("async", "r#async"),
112 ("await", "r#await"),
113 ("dyn", "r#dyn"),
114 ("abstract", "r#abstract"),
115 ("become", "r#become"),
116 ("box", "r#box"),
117 ("do", "r#do"),
118 ("final", "r#final"),
119 ("macro", "r#macro"),
120 ("override", "r#override"),
121 ("priv", "r#priv"),
122 ("typeof", "r#typeof"),
123 ("unsized", "r#unsized"),
124 ("virtual", "r#virtual"),
125 ("yield", "r#yield"),
126 ("try", "r#try"),
127];