enum_traits_macros 4.0.0

Procedural macros adding functionality to enums. Derives traits from the crate `enum_traits`
Documentation
use proc_macro2::TokenStream;
use syn::Fields;

fn enum_first_variant_ident(item: &syn::ItemEnum) -> &syn::Ident{
	let variant_first = item.variants.first().expect("`impl_enum_first` may only be applied to non-empty enums");
	if let Fields::Unit = variant_first.fields {} else {panic!("`impl_enum_first` may only be applied to enums where the first variant is an unit variant");}
	&variant_first.ident
}

fn enum_last_variant_ident(item: &syn::ItemEnum) -> &syn::Ident{
	let variant_last = item.variants.last().expect("`impl_enum_last` may only be applied to non-empty enums");
	if let Fields::Unit = variant_last.fields {} else {panic!("`impl_enum_last` may only be applied to enums where the last variant is an unit variant");}
	&variant_last.ident
}

pub fn gen_impl(item: syn::ItemEnum) -> TokenStream{
	let (impl_generics,ty_generics,where_clause) = item.generics.split_for_impl();
	let ident = &item.ident;
	let variant_first_ident = enum_first_variant_ident(&item);
	let variant_last_ident  = enum_last_variant_ident(&item);

	quote!{
		#[automatically_derived]
		impl #impl_generics ::enum_traits::Ends for #ident #ty_generics #where_clause{
			const FIRST: Self = #ident::#variant_first_ident;
			const LAST : Self = #ident::#variant_last_ident;
		}
	}
}

pub fn gen_attr_impl_first(attr: TokenStream,item: syn::ItemEnum) -> TokenStream{
	let (impl_generics,ty_generics,where_clause) = item.generics.split_for_impl();
	let ident = &item.ident;
	let variant_first_ident = enum_first_variant_ident(&item);

	let const_ident = syn::parse2::<syn::Ident>(attr)
		.expect("`impl_enum_first` expects an ident argument.");

	quote!{
		#item

		#[automatically_derived]
		impl #impl_generics #ident #ty_generics #where_clause{
			const #const_ident: Self = #ident::#variant_first_ident;
		}
	}
}

pub fn gen_attr_impl_last(attr: TokenStream,item: syn::ItemEnum) -> TokenStream{
	let (impl_generics,ty_generics,where_clause) = item.generics.split_for_impl();
	let ident = &item.ident;
	let variant_last_ident = enum_last_variant_ident(&item);

	let const_ident = syn::parse2::<syn::Ident>(attr)
		.expect("`impl_enum_first` expects an ident argument.");

	quote!{
		#item

		#[automatically_derived]
		impl #impl_generics #ident #ty_generics #where_clause{
			const #const_ident: Self = #ident::#variant_last_ident;
		}
	}
}