use proc_macro::TokenStream;
use quote::quote;
use syn::{
Data, DeriveInput, Field, Fields, Ident,
punctuated::Punctuated, token::Comma,
};
pub fn proc_tokens(input: TokenStream) -> TokenStream {
let ast: DeriveInput = syn::parse(input).unwrap();
match &ast.data {
Data::Struct(data_struct) => {
match &data_struct.fields {
Fields::Named(fields_named) => {
with_bounds(&ast.ident, &fields_named.named)
},
Fields::Unnamed(fields_unnamed) => {
with_bounds(&ast.ident, &fields_unnamed.unnamed)
},
Fields::Unit => {
without_bounds(&ast.ident)
},
}
},
Data::Enum(_data_enum) => {
panic!("Derive macro `Cast` does not support enum.")
},
Data::Union(data_union) => {
with_bounds(&ast.ident, &data_union.fields.named)
},
}
}
fn with_bounds(
ident: &Ident,
punctuated: &Punctuated<Field, Comma>,
) -> TokenStream {
let field_type = punctuated.iter().map(|field| &field.ty);
quote! {
impl castflip::Cast for #ident
where
#( #field_type: castflip::Cast, )*
{}
}.into()
}
fn without_bounds(ident: &Ident) -> TokenStream {
quote! {
impl castflip::Cast for #ident {}
}.into()
}