prometheus_client_derive_encode/
lib.rs1#![deny(dead_code)]
2#![deny(missing_docs)]
3#![deny(unused)]
4#![forbid(unsafe_code)]
5#![warn(missing_debug_implementations)]
6
7use proc_macro::TokenStream;
10use proc_macro2::TokenStream as TokenStream2;
11use quote::quote;
12use syn::DeriveInput;
13
14#[proc_macro_derive(EncodeLabelSet, attributes(prometheus))]
16pub fn derive_encode_label_set(input: TokenStream) -> TokenStream {
17 let ast: DeriveInput = syn::parse(input).unwrap();
18 let name = &ast.ident;
19
20 let body: TokenStream2 = match ast.clone().data {
21 syn::Data::Struct(s) => match s.fields {
22 syn::Fields::Named(syn::FieldsNamed { named, .. }) => named
23 .into_iter()
24 .map(|f| {
25 let attribute = f
26 .attrs
27 .iter()
28 .find(|a| a.path().is_ident("prometheus"))
29 .map(|a| a.parse_args::<syn::Ident>().unwrap().to_string());
30 let flatten = match attribute.as_deref() {
31 Some("flatten") => true,
32 Some(other) => {
33 panic!("Provided attribute '{other}', but only 'flatten' is supported")
34 }
35 None => false,
36 };
37 let ident = f.ident.unwrap();
38 if flatten {
39 quote! {
40 EncodeLabelSet::encode(&self.#ident, encoder)?;
41 }
42 } else {
43 let ident_string = KEYWORD_IDENTIFIERS
44 .iter()
45 .find(|pair| ident == pair.1)
46 .map(|pair| pair.0.to_string())
47 .unwrap_or_else(|| ident.to_string());
48
49 quote! {
50 let mut label_encoder = encoder.encode_label();
51 let mut label_key_encoder = label_encoder.encode_label_key()?;
52 EncodeLabelKey::encode(&#ident_string, &mut label_key_encoder)?;
53
54 let mut label_value_encoder = label_key_encoder.encode_label_value()?;
55 EncodeLabelValue::encode(&self.#ident, &mut label_value_encoder)?;
56
57 label_value_encoder.finish()?;
58 }
59 }
60 })
61 .collect(),
62 syn::Fields::Unnamed(_) => {
63 panic!("Can not derive Encode for struct with unnamed fields.")
64 }
65 syn::Fields::Unit => panic!("Can not derive Encode for struct with unit field."),
66 },
67 syn::Data::Enum(syn::DataEnum { .. }) => {
68 panic!("Can not derive Encode for enum.")
69 }
70 syn::Data::Union(_) => panic!("Can not derive Encode for union."),
71 };
72
73 let gen = quote! {
74 impl ::prometheus_client::encoding::EncodeLabelSet for #name {
75 fn encode(&self, encoder: &mut ::prometheus_client::encoding::LabelSetEncoder) -> ::core::result::Result<(), ::core::fmt::Error> {
76 use ::prometheus_client::encoding::EncodeLabel;
77 use ::prometheus_client::encoding::EncodeLabelKey;
78 use ::prometheus_client::encoding::EncodeLabelValue;
79
80 #body
81
82 ::core::result::Result::Ok(())
83 }
84 }
85 };
86
87 gen.into()
88}
89
90#[proc_macro_derive(EncodeLabelValue)]
92pub fn derive_encode_label_value(input: TokenStream) -> TokenStream {
93 let ast: DeriveInput = syn::parse(input).unwrap();
94 let name = &ast.ident;
95
96 let body = match ast.clone().data {
97 syn::Data::Struct(_) => {
98 panic!("Can not derive EncodeLabel for struct.")
99 }
100 syn::Data::Enum(syn::DataEnum { variants, .. }) => {
101 let match_arms: TokenStream2 = variants
102 .into_iter()
103 .map(|v| {
104 let ident = v.ident;
105 quote! {
106 #name::#ident => encoder.write_str(stringify!(#ident))?,
107 }
108 })
109 .collect();
110
111 quote! {
112 match self {
113 #match_arms
114 }
115 }
116 }
117 syn::Data::Union(_) => panic!("Can not derive Encode for union."),
118 };
119
120 let gen = quote! {
121 impl ::prometheus_client::encoding::EncodeLabelValue for #name {
122 fn encode(&self, encoder: &mut ::prometheus_client::encoding::LabelValueEncoder) -> ::core::result::Result<(), ::core::fmt::Error> {
123 use ::core::fmt::Write;
124
125 #body
126
127 ::core::result::Result::Ok(())
128 }
129 }
130 };
131
132 gen.into()
133}
134
135static KEYWORD_IDENTIFIERS: [(&str, &str); 48] = [
138 ("as", "r#as"),
139 ("break", "r#break"),
140 ("const", "r#const"),
141 ("continue", "r#continue"),
142 ("crate", "r#crate"),
143 ("else", "r#else"),
144 ("enum", "r#enum"),
145 ("extern", "r#extern"),
146 ("false", "r#false"),
147 ("fn", "r#fn"),
148 ("for", "r#for"),
149 ("if", "r#if"),
150 ("impl", "r#impl"),
151 ("in", "r#in"),
152 ("let", "r#let"),
153 ("loop", "r#loop"),
154 ("match", "r#match"),
155 ("mod", "r#mod"),
156 ("move", "r#move"),
157 ("mut", "r#mut"),
158 ("pub", "r#pub"),
159 ("ref", "r#ref"),
160 ("return", "r#return"),
161 ("static", "r#static"),
162 ("struct", "r#struct"),
163 ("trait", "r#trait"),
164 ("true", "r#true"),
165 ("type", "r#type"),
166 ("unsafe", "r#unsafe"),
167 ("use", "r#use"),
168 ("where", "r#where"),
169 ("while", "r#while"),
170 ("async", "r#async"),
171 ("await", "r#await"),
172 ("dyn", "r#dyn"),
173 ("abstract", "r#abstract"),
174 ("become", "r#become"),
175 ("box", "r#box"),
176 ("do", "r#do"),
177 ("final", "r#final"),
178 ("macro", "r#macro"),
179 ("override", "r#override"),
180 ("priv", "r#priv"),
181 ("typeof", "r#typeof"),
182 ("unsized", "r#unsized"),
183 ("virtual", "r#virtual"),
184 ("yield", "r#yield"),
185 ("try", "r#try"),
186];