diff --git a/README.md b/README.md index 2d3bb6c..ce5992a 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,48 @@ fn main() { } ``` +### Nameln + +```rust + +use vodca::Nameln; + +#[derive(Nameln)] +pub enum Events { + Created { id: i64 }, + Updated(T), + Deleted, +} + +/// generated by vodca +impl Enum { + #[allow(unused_variables, non_snake_case)] + pub fn name(&self) -> String { + let name = match self { + Enum::Created { id: i64 } => "Created", + Enum::Updated(T) => "Updated", + Enum::Deleted => "Deleted", + }; + name.to_string() + } +} +/// + +fn main() { + let i64: Enum = Enum::Created { id: 42 }; + let name = i64.name(); + assert_eq!(name, "Created"); + + let generics = Enum::Updated("Hello, world!".to_string()); + let name = generics.name(); + assert_eq!(name, "Updated"); + + let deleted: Enum<&str> = Enum::Deleted; + let name = deleted.name(); + assert_eq!(name, "Deleted"); +} +``` + ## Both ### Newln diff --git a/src/lib.rs b/src/lib.rs index 11eb29a..3325ee4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,9 @@ use proc_macro::TokenStream; use proc_macro2::{Ident, Span}; use quote::quote; -use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Fields, FieldsNamed, FieldsUnnamed}; +use syn::{ + parse_macro_input, Data, DataEnum, DataStruct, DeriveInput, Fields, FieldsNamed, FieldsUnnamed, +}; #[proc_macro_derive(Fromln)] pub fn derive_fromln(input: TokenStream) -> TokenStream { @@ -157,3 +159,30 @@ pub fn derive_references(input: TokenStream) -> TokenStream { } .into() } + +#[proc_macro_derive(Nameln)] +pub fn derive_name(input: TokenStream) -> TokenStream { + let ast = parse_macro_input!(input as DeriveInput); + let name = &ast.ident; + let generics = &ast.generics; + + let names = match ast.data { + Data::Enum(DataEnum { variants, .. }) => variants.into_iter().map(|variant| { + let variant_name = format!("{}", &variant.ident); + quote! { #name::#variant => #variant_name } + }), + _ => unimplemented!("Only enums are supported"), + }; + quote! { + impl #generics #name #generics { + #[allow(unused_variables, non_snake_case)] + pub fn name(&self) -> String { + let name = match self { + #(#names,)* + }; + name.to_string() + } + } + } + .into() +} diff --git a/tests/name.rs b/tests/name.rs new file mode 100644 index 0000000..f6c2af1 --- /dev/null +++ b/tests/name.rs @@ -0,0 +1,22 @@ +use vodca::Nameln; + +#[derive(Nameln)] +pub enum Enum { + I64 { id: i64 }, + Generics(T), + Deleted, +} + +fn main() { + let i64: Enum = Enum::I64 { id: 42 }; + let name = i64.name(); + assert_eq!(name, "I64"); + + let generics = Enum::Generics("Hello, world!".to_string()); + let name = generics.name(); + assert_eq!(name, "Generics"); + + let deleted: Enum<&str> = Enum::Deleted; + let name = deleted.name(); + assert_eq!(name, "Deleted"); +} diff --git a/tests/parse_test.rs b/tests/parse_test.rs index d88fa32..f24bd7f 100644 --- a/tests/parse_test.rs +++ b/tests/parse_test.rs @@ -3,6 +3,7 @@ fn test() { let try_test = trybuild::TestCases::new(); try_test.pass("tests/as_ref.rs"); try_test.pass("tests/from.rs"); + try_test.pass("tests/name.rs"); try_test.pass("tests/new.rs"); try_test.pass("tests/references.rs"); try_test.pass("tests/references_generics.rs");