opentelemetry_derive_impl/
lib.rs1use darling::{util::Ignored, FromDeriveInput};
2use proc_macro2::TokenStream;
3use quote::quote;
4use syn::{parse_macro_input, DeriveInput, Path};
5
6#[derive(FromDeriveInput)]
7#[darling(attributes(otel))]
8struct Options<Key, Variant> {
9 key: Key,
10 variant: Variant,
11}
12
13#[proc_macro_derive(Key, attributes(otel))]
14pub fn key(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
15 derive(input, key_impl)
16}
17
18fn key_impl(input: DeriveInput) -> syn::Result<TokenStream> {
19 let options = Options::<Option<String>, Option<Ignored>>::from_derive_input(&input)?;
20 let ident = input.ident;
21 let key = options.key.unwrap_or(ident.to_string().to_lowercase());
22 Ok(quote! {
23 impl #ident {
24 const KEY: opentelemetry::Key = opentelemetry::Key::from_static_str(#key);
25 }
26
27 #[automatically_derived]
28 impl From<&#ident> for opentelemetry::Key {
29 fn from(_: &#ident) -> Self {
30 #ident::KEY
31 }
32 }
33
34 #[automatically_derived]
35 impl From<#ident> for opentelemetry::Key {
36 fn from(_: #ident) -> Self {
37 #ident::KEY
38 }
39 }
40 })
41}
42
43#[proc_macro_derive(KeyValue)]
44pub fn key_value(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
45 derive(input, key_value_impl)
46}
47
48fn key_value_impl(input: DeriveInput) -> syn::Result<TokenStream> {
49 let ident = input.ident;
50 Ok(quote! {
51 #[automatically_derived]
52 impl From<&#ident> for opentelemetry::KeyValue {
53 fn from(value: &#ident) -> Self {
54 Self::new(value, value)
55 }
56 }
57
58 #[automatically_derived]
59 impl From<#ident> for opentelemetry::KeyValue {
60 fn from(value: #ident) -> Self {
61 Self::from(&value)
62 }
63 }
64 })
65}
66
67#[proc_macro_derive(StringValue)]
68pub fn string_value(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
69 derive(input, string_value_impl)
70}
71
72fn string_value_impl(input: DeriveInput) -> syn::Result<TokenStream> {
73 let ident = input.ident;
74 Ok(quote! {
75 const _: () = {
76 struct AssertToString where #ident: ToString;
77 };
78
79 #[automatically_derived]
80 impl From<&#ident> for opentelemetry::StringValue {
81 fn from(value: &#ident) -> Self {
82 value.to_string().into()
83 }
84 }
85
86 #[automatically_derived]
87 impl From<#ident> for opentelemetry::StringValue {
88 fn from(value: #ident) -> Self {
89 Self::from(&value)
90 }
91 }
92 })
93}
94
95#[proc_macro_derive(Value, attributes(otel))]
96pub fn value(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
97 derive(input, value_impl)
98}
99
100fn value_impl(input: DeriveInput) -> syn::Result<TokenStream> {
101 let options = Options::<Option<Ignored>, Path>::from_derive_input(&input)?;
102 let ident = input.ident;
103 let variant = options.variant;
104 Ok(quote! {
105 #[automatically_derived]
106 impl From<&#ident> for opentelemetry::Value {
107 fn from(value: &#ident) -> Self {
108 #variant::from(value).into()
109 }
110 }
111
112 #[automatically_derived]
113 impl From<#ident> for opentelemetry::Value {
114 fn from(value: #ident) -> Self {
115 Self::from(&value)
116 }
117 }
118 })
119}
120
121fn derive(
122 input: proc_macro::TokenStream,
123 f: fn(DeriveInput) -> syn::Result<TokenStream>,
124) -> proc_macro::TokenStream {
125 let input = parse_macro_input!(input as DeriveInput);
126 f(input)
127 .unwrap_or_else(syn::Error::into_compile_error)
128 .into()
129}