Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 58 additions & 13 deletions derive-encode/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,33 @@ pub fn derive_encode_label_set(input: TokenStream) -> TokenStream {
let ast: DeriveInput = syn::parse(input).unwrap();
let name = &ast.ident;

if let syn::Data::Struct(syn::DataStruct { ref fields, .. }) = ast.data {
for f in fields.iter() {
for a in &f.attrs {
if !a.path().is_ident("prometheus") {
continue;
}
match a.parse_args::<syn::Ident>() {
Ok(ident) if ident == "flatten" => {}
Ok(other) => {
let msg = format!(
"Provided attribute '{other}', but only 'flatten' is supported"
);
return quote! { compile_error!(#msg); }.into();
}
Err(_) => {
return quote! {
compile_error!(
"Attribute on `#[prometheus(...)]` must be an identifier, e.g. `#[prometheus(flatten)]`"
);
}
.into();
}
}
}
}
}

let body: TokenStream2 = match ast.clone().data {
syn::Data::Struct(s) => match s.fields {
syn::Fields::Named(syn::FieldsNamed { named, .. }) => named
Expand All @@ -27,13 +54,7 @@ pub fn derive_encode_label_set(input: TokenStream) -> TokenStream {
.iter()
.find(|a| a.path().is_ident("prometheus"))
.map(|a| a.parse_args::<syn::Ident>().unwrap().to_string());
let flatten = match attribute.as_deref() {
Some("flatten") => true,
Some(other) => {
panic!("Provided attribute '{other}', but only 'flatten' is supported")
}
None => false,
};
let flatten = attribute.as_deref() == Some("flatten");
let ident = f.ident.unwrap();
if flatten {
quote! {
Expand All @@ -60,14 +81,30 @@ pub fn derive_encode_label_set(input: TokenStream) -> TokenStream {
})
.collect(),
syn::Fields::Unnamed(_) => {
panic!("Can not derive Encode for struct with unnamed fields.")
return quote! {
compile_error!("Can not derive Encode for struct with unnamed fields.");
}
.into();
}
syn::Fields::Unit => {
return quote! {
compile_error!("Can not derive Encode for struct with unit field.");
}
.into();
}
syn::Fields::Unit => panic!("Can not derive Encode for struct with unit field."),
},
syn::Data::Enum(syn::DataEnum { .. }) => {
panic!("Can not derive Encode for enum.")
return quote! {
compile_error!("Can not derive Encode for enum.");
}
.into();
}
syn::Data::Union(_) => {
return quote! {
compile_error!("Can not derive Encode for union.");
}
.into();
}
syn::Data::Union(_) => panic!("Can not derive Encode for union."),
};

let gen = quote! {
Expand Down Expand Up @@ -95,7 +132,10 @@ pub fn derive_encode_label_value(input: TokenStream) -> TokenStream {

let body = match ast.clone().data {
syn::Data::Struct(_) => {
panic!("Can not derive EncodeLabel for struct.")
return quote! {
compile_error!("Can not derive EncodeLabel for struct.");
}
.into();
}
syn::Data::Enum(syn::DataEnum { variants, .. }) => {
let match_arms: TokenStream2 = variants
Expand All @@ -114,7 +154,12 @@ pub fn derive_encode_label_value(input: TokenStream) -> TokenStream {
}
}
}
syn::Data::Union(_) => panic!("Can not derive Encode for union."),
syn::Data::Union(_) => {
return quote! {
compile_error!("Can not derive Encode for union.");
}
.into();
}
};

let gen = quote! {
Expand Down
37 changes: 37 additions & 0 deletions derive-encode/tests/build/friendly-compilation-error-msg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use prometheus_client::encoding::EncodeLabelSet;
use prometheus_client::encoding::EncodeLabelValue;

// Unnamed struct fields: not supported by `EncodeLabelSet`.
#[derive(EncodeLabelSet)]
struct Unnamed(String);

// Unit struct: not supported by `EncodeLabelSet`.
#[derive(EncodeLabelSet)]
struct UnitStruct;

// Enum: not supported by `EncodeLabelSet`.
#[derive(EncodeLabelSet)]
enum NotAllowedSet {
A,
B,
}

// Unknown attribute: only `#[prometheus(flatten)]` is accepted.
#[derive(EncodeLabelSet)]
struct BadAttr {
#[prometheus(unknown)]
a: u64,
}

// Struct: not supported by `EncodeLabelValue` (only enums are).
#[derive(EncodeLabelValue)]
struct StructForValue;

// Union: not supported by either derive.
#[derive(EncodeLabelSet)]
union UnionSet {
a: u32,
b: f32,
}

fn main() {}
47 changes: 47 additions & 0 deletions derive-encode/tests/build/friendly-compilation-error-msg.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
error: Can not derive Encode for struct with unnamed fields.
--> tests/build/friendly-compilation-error-msg.rs:5:10
|
5 | #[derive(EncodeLabelSet)]
| ^^^^^^^^^^^^^^
|
= note: this error originates in the derive macro `EncodeLabelSet` (in Nightly builds, run with -Z macro-backtrace for more info)

error: Can not derive Encode for struct with unit field.
--> tests/build/friendly-compilation-error-msg.rs:9:10
|
9 | #[derive(EncodeLabelSet)]
| ^^^^^^^^^^^^^^
|
= note: this error originates in the derive macro `EncodeLabelSet` (in Nightly builds, run with -Z macro-backtrace for more info)

error: Can not derive Encode for enum.
--> tests/build/friendly-compilation-error-msg.rs:13:10
|
13 | #[derive(EncodeLabelSet)]
| ^^^^^^^^^^^^^^
|
= note: this error originates in the derive macro `EncodeLabelSet` (in Nightly builds, run with -Z macro-backtrace for more info)

error: Provided attribute 'unknown', but only 'flatten' is supported
--> tests/build/friendly-compilation-error-msg.rs:20:10
|
20 | #[derive(EncodeLabelSet)]
| ^^^^^^^^^^^^^^
|
= note: this error originates in the derive macro `EncodeLabelSet` (in Nightly builds, run with -Z macro-backtrace for more info)

error: Can not derive EncodeLabel for struct.
--> tests/build/friendly-compilation-error-msg.rs:27:10
|
27 | #[derive(EncodeLabelValue)]
| ^^^^^^^^^^^^^^^^
|
= note: this error originates in the derive macro `EncodeLabelValue` (in Nightly builds, run with -Z macro-backtrace for more info)

error: Can not derive Encode for union.
--> tests/build/friendly-compilation-error-msg.rs:31:10
|
31 | #[derive(EncodeLabelSet)]
| ^^^^^^^^^^^^^^
|
= note: this error originates in the derive macro `EncodeLabelSet` (in Nightly builds, run with -Z macro-backtrace for more info)
3 changes: 2 additions & 1 deletion derive-encode/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,5 +205,6 @@ fn flatten() {
#[test]
fn build() {
let t = trybuild::TestCases::new();
t.pass("tests/build/redefine-prelude-symbols.rs")
t.pass("tests/build/redefine-prelude-symbols.rs");
t.compile_fail("tests/build/friendly-compilation-error-msg.rs");
}