@@ -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