Skip to content

Commit

Permalink
Add values() method and document all methods in UnitEnum macro
Browse files Browse the repository at this point in the history
  • Loading branch information
RenaudDenis committed Jul 2, 2024
1 parent ac805fd commit cffef75
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 83 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Unreleased

# Version 1.1.0 (2024-06-27)

- Add `values()` method and document all methods in UnitEnum macro

# Version 1.0.0 (2024-03-17)

- Initial Revision
14 changes: 7 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "unit-enum"
version = "1.0.0"
version = "1.1.0"
authors = ["Renaud Denis <[email protected]>"]
description = "A procedural macro for deriving ordinal methods in unit-like enums for Rust."
license = "MIT OR Apache-2.0"
Expand Down
49 changes: 32 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,55 @@
# UnitEnum
# UnitEnum Crate Documentation

The `unit-enum` crate introduces a procedural macro `UnitEnum` for Rust developers working with enums that consist
entirely of unit variants. This macro enhances such enums by automatically implementing methods to manage enum variants
more effectively, promoting ease of use and reducing boilerplate code.
The `unit-enum` crate provides a procedural macro `UnitEnum` designed to enhance enums in Rust, particularly those
consisting solely of unit variants. This macro simplifies working with such enums by providing methods to convert
between enum variants and their ordinal positions, along with utility methods to count the number of variants and iterate over them.

## Features

- **Ordinal Methods**: Easily obtain the ordinal of an enum variant or convert an ordinal value back to a corresponding
enum variant.
- **Variant Count**: Retrieve the total number of variants in an enum.
- `ordinal`: Retrieve the ordinal of an enum variant, starting from 0.
- `from_ordinal`: Convert an ordinal back to an enum variant, if possible.
- `len`: Get the total number of variants in the enum.
- `values`: Returns an iterator over all variants of the enum, allowing for easy iteration and handling of each variant.

## Limitations

- Applicable only to enums with unit variants.
- Enums with data-carrying or tuple variants are not supported and will result in a compile-time error.

## Installation

To use `unit-enum` in your project, add it as a dependency in your `Cargo.toml`:
Add the following to your `Cargo.toml`:

```toml
[dependencies]
unit-enum = "1.0.0"
unit-enum = "1.1.0"
```

## Quick Start

```rust
use unit_enum::UnitEnum;

#[derive(UnitEnum)]
#[derive(Debug, Clone, Copy, PartialEq, UnitEnum)]
enum Color {
Red,
Green,
Blue,
Red,
Green,
Blue
}

let green = Color::Green;
assert_eq!(green.ordinal(), 1);
assert_eq!(Color::from_ordinal(1), Some(Color::Green));
assert_eq!(Color::len(), 3);
fn main() {
println!("Ordinal of Green: {:?}", Color::Green.ordinal());
// Ordinal of Green: 1

println!("Value of ordinal 2: {:?}", Color::from_ordinal(2));
// Value of ordinal 2: Some(Blue)

println!("Number of Color variants: {:?}", Color::len());
// Number of Color variants: 3

println!("List of Color variants: {:?}", Color::values().collect::<Vec<_>>());
// List of Color variants: [Red, Green, Blue]
}
```

## Contributing
Expand Down
16 changes: 12 additions & 4 deletions examples/example.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
use unit_enum::UnitEnum;

#[derive(Debug, Clone, Copy, UnitEnum)]
#[derive(Debug, Clone, Copy, PartialEq, UnitEnum)]
enum Color {
Red,
Green,
Blue
}

fn main() {
println!("Ordinal of Green: {:?}", Color::Green.ordinal());
println!("Value of ordinal 2: {:?}", Color::from_ordinal(2));
println!("Number of Color variants: {:?}", Color::len());
println!("Ordinal of Green: {:?}", Color::Green.ordinal());
// Ordinal of Green: 1

println!("Value of ordinal 2: {:?}", Color::from_ordinal(2));
// Value of ordinal 2: Some(Blue)

println!("Number of Color variants: {:?}", Color::len());
// Number of Color variants: 3

println!("List of Color variants: {:?}", Color::values().collect::<Vec<_>>());
// List of Color variants: [Red, Green, Blue]
}
49 changes: 0 additions & 49 deletions src/lib.md

This file was deleted.

25 changes: 20 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![doc = include_str!("lib.md")]

use proc_macro::TokenStream;

use quote::quote;
Expand All @@ -26,7 +24,7 @@ fn impl_unit_enum(ast: &DeriveInput) -> TokenStream {
match &variant.fields {
Fields::Unit => {
quote! { #name::#variant_name => #index, }
},
}
_ => panic!("UnitEnum only supports unit variants (no fields)"),
}
});
Expand All @@ -36,25 +34,42 @@ fn impl_unit_enum(ast: &DeriveInput) -> TokenStream {
quote! { #index => Some(#name::#variant_name), }
});

let values_arms = (0..num_variants).map(|index| {
quote! { #name::from_ordinal(#index).unwrap() }
});

let gen = quote! {
impl #name {
/// Returns the zero-based ordinal of the enum variant.
pub fn ordinal(&self) -> usize {
match self {
#( #ordinal_match_arms )*
}
}

pub fn from_ordinal(ord: usize) -> Option<Self> {
/// Converts a zero-based ordinal to an enum variant, if possible.
///
/// Returns `None` if the ordinal is out of range.
pub fn from_ordinal(ord: usize) -> Option<Self> {
match ord {
#( #from_ordinal_match_arms )*
_ => None,
}
}

/// Returns the total number of variants in the enum.
pub fn len() -> usize {
#num_variants
}

/// Returns an iterator over all variants of the enum.
///
/// This method creates an iterator that yields each variant in
/// definition order, starting from the first variant.
pub fn values() -> impl Iterator<Item = Self> {
vec![ #( #values_arms ),* ].into_iter()
}
}
};
gen.into()
}
}

0 comments on commit cffef75

Please sign in to comment.