extern crate proc_macro;
use proc_macro2::TokenStream;
use quote::quote;
use syn::{parse2, parse_quote, spanned::Spanned, Error, ItemEnum};
#[doc(hidden)]
#[proc_macro_attribute]
pub fn tyenum(_attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
let item: TokenStream = item.into();
let mut tyenum: ItemEnum = parse2(item).unwrap();
let name = &tyenum.ident;
let mut impls = Vec::new();
for v in tyenum.variants.iter_mut() {
let mut iter = v.fields.iter();
if let Some(f) = iter.next() {
let ident = &v.ident;
let ty = &f.ty;
impls.push(quote! {
impl From<#ty> for #name {
fn from(variant: #ty) -> Self {
#name::#ident(variant)
}
}
});
if let Some(f) = iter.next() {
return Error::new(f.span(), "maximum one field in variants allowed").to_compile_error().into();
}
} else {
drop(iter);
let ident = &v.ident;
impls.push(quote! {
impl From<#ident> for #name {
fn from(variant: #ident) -> Self {
#name::#ident(variant)
}
}
});
*v = parse_quote!(#ident(#ident));
}
}
quote! (
#tyenum
#(#impls)*
)
.into()
}