use proc_macro2::TokenStream;
use quote::quote;
use syn::Data;
use syn::DataEnum;
use syn::DeriveInput;
use syn::Result;
fn impl_try_from_num(data: &DataEnum) -> Result<TokenStream> {
let mut branch_token = quote!();
for variant in &data.variants {
let var_ident = &variant.ident;
branch_token = quote! {
#branch_token
if (Self::#var_ident as i32).eq(value) {
return Ok(Self::#var_ident);
}
};
}
let result = quote! {
fn try_from(value: &i32) -> Result<Self, Self::Error> {
#branch_token
Err(())
}
};
Ok(result)
}
fn impl_try_from_str(data: &DataEnum) -> Result<TokenStream> {
let mut branch_token = quote!();
for variant in &data.variants {
let var_ident = &variant.ident;
let var_ident_str = var_ident.to_string();
branch_token = quote! {
#branch_token
#var_ident_str => Ok(Self::#var_ident),
};
}
let result = quote! {
fn try_from(value: &String) -> Result<Self, Self::Error> {
match value.as_str() {
#branch_token
_ => Err(()),
}
}
};
Ok(result)
}
pub fn expand(input: DeriveInput) -> Result<TokenStream> {
let ty = &input.ident;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let result_token = match &input.data {
Data::Struct(_) => unimplemented!(),
Data::Enum(data) => {
let try_from_num = impl_try_from_num(data)?;
let try_from_str = impl_try_from_str(data)?;
quote! {
impl #impl_generics TryFrom<&i32> for #ty #ty_generics #where_clause {
type Error = ();
#try_from_num
}
impl #impl_generics TryFrom<&String> for #ty #ty_generics #where_clause {
type Error = ();
#try_from_str
}
}
}
Data::Union(_) => unimplemented!(),
};
Ok(result_token)
}