Skip to content

Commit 580cf2c

Browse files
committed
Add support for 'skip_encoding_if' for structs that derives EncodeLabelSet
Signed-off-by: Cristian George ANDREI <crandrei@bitdefender.com>
1 parent 6bb0b10 commit 580cf2c

File tree

1 file changed

+60
-28
lines changed

1 file changed

+60
-28
lines changed

derive-encode/src/lib.rs

Lines changed: 60 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,38 +22,67 @@ pub fn derive_encode_label_set(input: TokenStream) -> TokenStream {
2222
syn::Fields::Named(syn::FieldsNamed { named, .. }) => named
2323
.into_iter()
2424
.map(|f| {
25-
let attribute = f
26-
.attrs
25+
let ident = f.ident.unwrap();
26+
let ident_string = KEYWORD_IDENTIFIERS
2727
.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")
28+
.find(|pair| ident == pair.1)
29+
.map(|pair| pair.0.to_string())
30+
.unwrap_or_else(|| ident.to_string());
31+
32+
let mut flatten = false;
33+
let mut skip_encoding_if_fn: Option<syn::Path> = None;
34+
35+
for attr in f.attrs.iter().filter(|a| a.path().is_ident("prometheus")) {
36+
let result = attr.parse_nested_meta(|meta| {
37+
if meta.path.is_ident("flatten") {
38+
flatten = true;
39+
return Ok(());
40+
}
41+
42+
if meta.path.is_ident("skip_encoding_if") {
43+
let lit: syn::LitStr = meta.value()?.parse()?;
44+
match lit.parse::<syn::Path>() {
45+
Ok(path) => {
46+
skip_encoding_if_fn = Some(path);
47+
Ok(())
48+
}
49+
Err(err) => Err(err),
50+
}?;
51+
return Ok(());
52+
}
53+
54+
Err(meta.error("unsupported #[prometheus(..)] attribute"))
55+
});
56+
57+
if let Err(err) = result {
58+
return err.to_compile_error();
3459
}
35-
None => false,
36-
};
37-
let ident = f.ident.unwrap();
60+
}
61+
3862
if flatten {
3963
quote! {
40-
EncodeLabelSet::encode(&self.#ident, encoder)?;
64+
prometheus_client::encoding::EncodeLabelSet::encode(&self.#ident, encoder)?;
65+
}
66+
} else if let Some(skip_fn) = skip_encoding_if_fn {
67+
quote! {
68+
if !(#skip_fn(&self.#ident)) {
69+
let mut label_encoder = encoder.encode_label();
70+
let mut label_key_encoder = label_encoder.encode_label_key()?;
71+
prometheus_client::encoding::EncodeLabelKey::encode(&#ident_string, &mut label_key_encoder)?;
72+
73+
let mut label_value_encoder = label_key_encoder.encode_label_value()?;
74+
prometheus_client::encoding::EncodeLabelValue::encode(&self.#ident, &mut label_value_encoder)?;
75+
label_value_encoder.finish()?;
76+
}
4177
}
4278
} 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-
4979
quote! {
5080
let mut label_encoder = encoder.encode_label();
5181
let mut label_key_encoder = label_encoder.encode_label_key()?;
52-
EncodeLabelKey::encode(&#ident_string, &mut label_key_encoder)?;
82+
prometheus_client::encoding::EncodeLabelKey::encode(&#ident_string, &mut label_key_encoder)?;
5383

5484
let mut label_value_encoder = label_key_encoder.encode_label_value()?;
55-
EncodeLabelValue::encode(&self.#ident, &mut label_value_encoder)?;
56-
85+
prometheus_client::encoding::EncodeLabelValue::encode(&self.#ident, &mut label_value_encoder)?;
5786
label_value_encoder.finish()?;
5887
}
5988
}
@@ -64,22 +93,25 @@ pub fn derive_encode_label_set(input: TokenStream) -> TokenStream {
6493
}
6594
syn::Fields::Unit => panic!("Can not derive Encode for struct with unit field."),
6695
},
67-
syn::Data::Enum(syn::DataEnum { .. }) => {
96+
syn::Data::Enum(_) => {
6897
panic!("Can not derive Encode for enum.")
6998
}
7099
syn::Data::Union(_) => panic!("Can not derive Encode for union."),
71100
};
72101

73102
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;
103+
impl prometheus_client::encoding::EncodeLabelSet for #name {
104+
fn encode(
105+
&self,
106+
encoder: &mut prometheus_client::encoding::LabelSetEncoder,
107+
) -> std::result::Result<(), std::fmt::Error> {
108+
use prometheus_client::encoding::EncodeLabel;
109+
use prometheus_client::encoding::EncodeLabelKey;
110+
use prometheus_client::encoding::EncodeLabelValue;
79111

80112
#body
81113

82-
::core::result::Result::Ok(())
114+
Ok(())
83115
}
84116
}
85117
};

0 commit comments

Comments
 (0)