use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, Fields};
#[proc_macro_derive(EasyFrom, attributes(from))]
pub fn derive_from(stream: TokenStream) -> TokenStream {
let input = parse_macro_input!(stream as DeriveInput);
let name = &input.ident;
let generics = &input.generics;
let mut out = TokenStream::new();
match input.data {
Data::Enum(e) => {
for v in e.variants.iter() {
let variant_name = &v.ident;
match &v.fields {
Fields::Unnamed(f) => {
let unnamed = &f.unnamed;
if unnamed.len() != 1 {
continue;
}
let field = &unnamed[0];
let attrs = &field.attrs;
if attrs.len() != 1 {
continue;
}
let attr = &attrs[0];
let path = &attr.path;
let segments = &path.segments;
if segments.len() != 1 {
continue;
}
let segment = &segments[0];
let ident = &segment.ident;
if ident != "e::format_ident!("from") {
continue;
}
let ty = &field.ty;
out.extend([TokenStream::from(quote! {
impl #generics core::convert::From<#ty> for #name #generics {
fn from(t: #ty) -> Self {
Self::#variant_name(t)
}
}
})]);
}
_ => (),
}
}
}
_ => unimplemented!(),
}
out
}