Crates.io | unit-enum |
lib.rs | unit-enum |
version | 1.4.0 |
source | src |
created_at | 2024-03-17 13:41:45.128105 |
updated_at | 2024-10-28 21:42:52.763324 |
description | A procedural macro for deriving ordinal methods in unit-like enums for Rust. |
homepage | |
repository | https://github.com/tylium/unit-enum |
max_upload_size | |
id | 1176504 |
size | 44,564 |
The unit-enum
crate provides a procedural macro UnitEnum
designed to enhance enums in Rust, particularly those
consisting of unit variants. This macro simplifies working with such enums by providing useful utility methods.
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.from_discriminant
: Convert a discriminant back to an enum variant.len
: Get the total number of unit variants in the enum (excluding the "other" variant if present).values
: Returns an iterator over all unit variants of the enum.The macro supports two types of enums:
Add the following to your Cargo.toml
:
[dependencies]
unit-enum = "1.4.0"
use unit_enum::UnitEnum;
#[derive(Debug, Clone, Copy, PartialEq, UnitEnum)]
#[repr(i16)] // Specify the discriminant type (optional, defaults to i32)
enum Color {
Red = 10,
Green, // 11
Blue = 45654
}
fn main() {
// Get the name of a variant
assert_eq!(Color::Blue.name(), "Blue");
// Get the ordinal (position) of a variant
assert_eq!(Color::Green.ordinal(), 1);
// Convert from ordinal back to variant
assert_eq!(Color::from_ordinal(2), Some(Color::Blue));
assert_eq!(Color::from_ordinal(4), None);
// Get the discriminant value (respects the repr type)
assert_eq!(Color::Blue.discriminant(), 45654);
assert_eq!(Color::Green.discriminant(), 11);
// Convert from discriminant back to variant
assert_eq!(Color::from_discriminant(10), Some(Color::Red));
assert_eq!(Color::from_discriminant(0), None);
// Get the total number of unit variants
assert_eq!(Color::len(), 3);
// Iterate over all variants
assert_eq!(
Color::values().collect::<Vec<_>>(),
vec![Color::Red, Color::Green, Color::Blue]
);
}
use unit_enum::UnitEnum;
#[derive(Debug, Clone, Copy, PartialEq, UnitEnum)]
#[repr(u16)] // repr attribute is required when using an "other" variant
enum Status {
Active = 1,
Inactive = 2,
#[unit_enum(other)]
Unknown(u16), // type must match repr
}
fn main() {
// from_discriminant always returns a value when "other" variant is present
assert_eq!(Status::from_discriminant(1), Status::Active);
assert_eq!(Status::from_discriminant(42), Status::Unknown(42));
// ordinal treats "other" as the last variant
assert_eq!(Status::Active.ordinal(), 0);
assert_eq!(Status::Unknown(42).ordinal(), 2);
// len returns only the number of unit variants
assert_eq!(Status::len(), 2);
// values iterates only over unit variants
assert_eq!(
Status::values().collect::<Vec<_>>(),
vec![Status::Active, Status::Inactive]
);
}
The crate respects the enum's #[repr]
attribute to determine the type of discriminant values. Supported types include:
#[repr(i8)]
, #[repr(i16)]
, #[repr(i32)]
, #[repr(i64)]
, #[repr(i128)]
#[repr(u8)]
, #[repr(u16)]
, #[repr(u32)]
, #[repr(u64)]
, #[repr(u128)]
If no #[repr]
attribute is specified, the discriminant type defaults to i32
. Note that when using an "other" variant, the #[repr]
attribute is required and must match the type of the "other" variant's field.
#[derive(UnitEnum)]
#[repr(u8)] // Use u8 for discriminants
enum SmallEnum {
A, // 0u8
B, // 1u8
C // 2u8
}
#[derive(UnitEnum)]
#[repr(i64)] // Use i64 for large discriminants
enum LargeEnum {
A = -1_000_000,
B = 5_000_000,
#[unit_enum(other)]
Other(i64) // type matches repr
}
When using an "other" variant, the following requirements must be met:
#[repr(type)]
attribute#[unit_enum(other)]
Contributions are welcome! Please feel free to submit pull requests or open issues on our GitHub repository.
This project is licensed under either of MIT or Apache-2.0, at your choice.