#![warn(clippy::pedantic)]
use proc_macro::TokenStream;
use quote::quote;
use syn::{DeriveInput, parse_macro_input};
#[proc_macro_derive(Identifier)]
pub fn uds_identifier_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
if let Err(e) = validate_identifier_shape(&input) {
return e.to_compile_error().into();
}
let name = &input.ident;
let expanded = quote! {
impl Identifier for #name {}
};
TokenStream::from(expanded)
}
fn validate_identifier_shape(input: &DeriveInput) -> Result<(), syn::Error> {
match &input.data {
syn::Data::Enum(_) => Ok(()),
syn::Data::Struct(s) => {
if let syn::Fields::Named(fields) = &s.fields {
if fields.named.len() == 1 {
Ok(())
} else {
Err(syn::Error::new_spanned(
&s.fields,
"Identifier can only be derived for structs with a single member",
))
}
} else {
Ok(())
}
}
syn::Data::Union(u) => Err(syn::Error::new_spanned(
u.union_token,
"Identifier can only be derived for enums and structs",
)),
}
}