From 045ac49bd7af565e99f5061ee8e25c5d5bd44518 Mon Sep 17 00:00:00 2001 From: Renaud Denis Date: Mon, 15 Jul 2024 17:41:40 +0200 Subject: [PATCH] Add `name()` method --- CHANGELOG.md | 4 ++++ Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 6 +++++- examples/example.rs | 3 +++ src/lib.rs | 16 ++++++++++++++++ 6 files changed, 30 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43d8918..7352009 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Unreleased +# Version 1.3.0 (2024-07-15) + +- Add `name()` method + # Version 1.2.0 (2024-07-02) - Add `discriminant()` and `from_discriminant(num)` methods diff --git a/Cargo.lock b/Cargo.lock index 8b9a612..ddb81bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,7 +39,7 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unit-enum" -version = "1.2.0" +version = "1.3.0" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 74af89f..b9db9e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "unit-enum" -version = "1.2.0" +version = "1.3.0" authors = ["Renaud Denis "] description = "A procedural macro for deriving ordinal methods in unit-like enums for Rust." license = "MIT OR Apache-2.0" diff --git a/README.md b/README.md index 277d8be..5468667 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ consisting solely of unit variants. This macro simplifies working with such enum ## Features +- `name`: Retrieve the name of an enum variant. - `ordinal`: Retrieve the ordinal of an enum variant, starting from 0. - `from_ordinal`: Convert an ordinal back to an enum variant, if possible. - `discriminant`: Retrieve the discriminant of an enum variant. @@ -23,7 +24,7 @@ Add the following to your `Cargo.toml`: ```toml [dependencies] -unit-enum = "1.2.0" +unit-enum = "1.3.0" ``` ## Quick Start @@ -39,6 +40,9 @@ enum Color { } fn main() { + println!("Name of Blue: {:?}", Color::Blue.name()); + // Name of Blue: "Blue" + println!("Ordinal of Green: {:?}", Color::Green.ordinal()); // Ordinal of Green: 1 diff --git a/examples/example.rs b/examples/example.rs index 1a984b1..c6fda88 100644 --- a/examples/example.rs +++ b/examples/example.rs @@ -8,6 +8,9 @@ enum Color { } fn main() { + println!("Name of Blue: {:?}", Color::Blue.name()); + // Name of Blue: "Blue" + println!("Ordinal of Green: {:?}", Color::Green.ordinal()); // Ordinal of Green: 1 diff --git a/src/lib.rs b/src/lib.rs index 7ba2167..f13f25f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,14 @@ fn impl_unit_enum(ast: &DeriveInput) -> TokenStream { let variants = &data.variants; let num_variants = variants.len(); // Count the number of variants + let name_match_arms = variants.iter().enumerate().map(|(index, variant)| { + let variant_name = &variant.ident; + match &variant.fields { + Fields::Unit => quote! { #name::#variant_name => stringify!(#variant_name) }, + _ => panic!("UnitEnum only supports unit variants (no fields)"), + } + }); + let ordinal_match_arms = variants.iter().enumerate().map(|(index, variant)| { let variant_name = &variant.ident; match &variant.fields { @@ -40,6 +48,13 @@ fn impl_unit_enum(ast: &DeriveInput) -> TokenStream { let gen = quote! { impl #name { + /// Returns the name of the enum variant. + pub fn name(&self) -> &str { + match self { + #(#name_match_arms,)* + } + } + /// Returns the zero-based ordinal of the enum variant. pub fn ordinal(&self) -> usize { match self { @@ -85,6 +100,7 @@ fn impl_unit_enum(ast: &DeriveInput) -> TokenStream { /// definition order, starting from the first variant. pub fn values() -> impl Iterator { vec![#(#values_arms,)*].into_iter() + } } };