type-change 0.1.0

Convert between different types of the same field name
Documentation
use quote::quote;
use syn::Attribute;

pub fn derive(ast: syn::DeriveInput) -> proc_macro2::TokenStream {
    let name = &ast.ident;
    let arg_name = syn::Ident::new("pre_state", proc_macro2::Span::call_site());
    let (from_type, inits) = match ast.data {
        syn::Data::Struct(ref s) => match s.fields {
            syn::Fields::Named(ref named) => {
                let from_type = parse_attributes(&ast.attrs).0;
                let fields: Vec<_> = named
                    .named
                    .iter()
                    .map(|f| {
                        let field = f.ident.clone().expect("unexpected field");
                        quote!(#field: #arg_name.#field.into())
                    })
                    .collect();
                let inits = quote!({ #(#fields), * });
                (from_type, inits)
            }
            syn::Fields::Unnamed(ref unnamed) => {
                let types: Vec<_> = unnamed.unnamed.iter().map(|f| f.ty.clone()).collect();
                if types.len() > 1 {
                    panic!("tuple length is overed")
                }
                let from_type = types.first().unwrap().clone();
                let inits = quote!((#arg_name));
                (from_type, inits)
            }
            syn::Fields::Unit => unimplemented!(),
        },
        _ => panic!("support for `struct` only."),
    };

    quote!(
        impl From<#from_type> for #name {
            fn from(#arg_name: #from_type) -> #name {
                #name #inits
            }
        }
    )
}

fn parse_attributes(attributes: &[Attribute]) -> FromAttributes {
    let mut attrs: Vec<syn::Result<FromAttributes>> =
        attributes.iter().map(|attr| attr.parse_args()).collect();
    match attrs.pop() {
        Some(Ok(attr)) => attr,
        Some(Err(err)) => panic!("{}", err),
        _ => panic!("must be specified attribute. for example `#[from(State1)]`"),
    }
}

struct FromAttributes(syn::Type);
impl syn::parse::Parse for FromAttributes {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<FromAttributes> {
        let ty = input.parse()?;
        Ok(FromAttributes(ty))
    }
}