8 releases (4 breaking)
0.5.0 | Nov 12, 2024 |
---|---|
0.4.0 | Nov 4, 2024 |
0.3.0 | Nov 2, 2024 |
0.2.3 | Oct 29, 2024 |
0.1.0 | Oct 19, 2024 |
#115 in Value formatting
199 downloads per month
33KB
571 lines
enum_ids
Procedural Macro
enum_ids
is a procedural attribute macro designed to generate a companion enum with only the variant names from an existing enum. It provides customizable options to control attribute inheritance, method naming, visibility, and the naming of the generated enum.
Usage
Apply the #[enum_ids]
attribute to your enum to automatically generate a corresponding ID enum and a getter method.
use enum_ids::enum_ids;
#[enum_ids]
#[derive(Debug, Clone)]
pub enum Kind {
A(i32),
B { value: String },
C,
}
fn main() {
let kind_a = Kind::A(10);
let id_a = kind_a.id();
println!("{:?}", id_a); // Outputs: A
}
The macro generates:
#[derive(Debug, Clone)]
pub enum Kind {
A(i32),
B { value: String },
C,
}
impl Kind {
pub fn id(&self) -> KindId {
match self {
Kind::A(..) => KindId::A,
Kind::B { .. } => KindId::B,
Kind::C => KindId::C,
}
}
}
#[derive(Debug, Clone)]
pub enum KindId {
A,
B,
C,
}
fn main() {
let kind_a = Kind::A(10);
let id_a = kind_a.id();
println!("{:?}", id_a); // Outputs: A
}
Supported Attributes
The enum_ids
macro supports various attributes to customize its behavior. These attributes can be combined as needed.
#[enum_ids]
- Inherits all derive attributes from the parent enum and names the getter method id()
.
Default: The generated enum will be named by appending Id to the parent enum's name (e.g., KindId for Kind).
#[enum_ids(derive = "Trait1, Trait2, ...")]
- Does not inherit derive attributes from the parent enum but adds the specified derive traits.
Example:
#[enum_ids(derive = "Serialize, Clone")]
pub enum Kind {
A(i32),
B(String),
C,
}
#[enum_ids(no_derive)]
- Does not add any derive attributes to the generated enum, regardless of the parent enum's attributes.
Example:
#[enum_ids(no_derive)]
pub enum Kind {
A(i32),
B(String),
C,
}
#[enum_ids(getter = "method_name")]
- Defines a custom name for the getter method instead of the default id()
.
Example:
#[enum_ids(getter = "get_id")]
pub enum Kind {
A(i32),
B(String),
C,
}
#[enum_ids(name = "CustomName")]
- Manually sets the name of the generated enum instead of using the default naming convention (ParentNameId).
Example:
#[enum_ids(name = "KindIdentifier")]
pub enum Kind {
A(i32),
B(String),
C,
}
#[enum_ids(public)]
- Makes the generated enum pub, regardless of the parent enum's visibility.
Example:
#[enum_ids(public)]
pub enum Kind {
A(i32),
B(String),
C,
}
#[enum_ids(not_public)]
- Makes the generated enum non-public (private), overriding any inherited visibility from the parent enum.
Example:
#[enum_ids(not_public)]
pub enum Kind {
A(i32),
B(String),
C,
}
#[enum_ids(display)]
- Will add implementation of std::fmt::Display
to generated enum.
Example:
#[enum_ids(dispaly)]
pub enum Kind {
A(i32),
B(String),
C,
}
Will genarate in addition
impl std::fmt::Disaply for KindId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
KindId::A => "Kind::A",
KindId::B => "Kind::B",
KindId::C => "Kind::C",
}
)
}
}
#[enum_ids(display_variants)]
- Will add implementation of std::fmt::Display
to generated enum using only variant's names (without enum's name).
Example:
#[enum_ids(display_variants)]
pub enum Kind {
A(i32),
B(String),
C,
}
Will genarate in addition
impl std::fmt::Disaply for KindId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
KindId::A => "A",
KindId::B => "B",
KindId::C => "C",
}
)
}
}
#[enum_ids(display_from_value)]
- Will add implementation of std::fmt::Display
to origin enum.
Note this option is available only for single unnamed fields.
Example:
#[enum_ids(display_from_value)]
pub enum Kind {
A(i32),
B(String),
C(f64),
}
Will genarate in addition
impl std::fmt::Disaply for Kind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
KindId::A(v) => v.to_string(),
KindId::B(v) => v.to_string(),
KindId::C(v) => v.to_string(),
}
)
}
}
Combined Attributes
You can combine multiple attributes to achieve the desired configuration. For example:
#[enum_ids(derive = "Serialize", getter = "get_id", name = "KindIdentifier", public)]
#[derive(Debug, Clone)]
pub enum Kind {
A(i32),
B { value: String },
C,
}
This will generate:
#[derive(Serialize)]
pub enum KindIdentifier {
A,
B,
C,
}
impl Kind {
pub fn get_id(&self) -> KindIdentifier {
match self {
A(..) => KindIdentifier:A,
B {..} => KindIdentifier:B,
C => KindIdentifier::C,
}
}
}
Getting ID of parent enum
In case if attribute getter
hasn't been used, getting of ID would be possible on method id()
of parent enum.
Example
use enum_ids::enum_ids;
#[enum_ids]
#[derive(Debug, Clone)]
pub enum Kind {
A(i32),
B { value: String },
C,
}
fn main() {
assert_eq!(Kind::A(10).id(), KindId::A);
}
Getting a full list of all IDs
enum_ids
also gives the possibility to get a full list of all IDs with method as_vec
. It will return vector of all IDs.
Example
use enum_ids::enum_ids;
#[enum_ids]
#[derive(Debug, Clone)]
pub enum Kind {
A(i32),
B { value: String },
C,
}
fn main() {
let mut count = 0;
let mut all = KindId::as_vec().into_iter();
while let Some(id) = all.next() {
println!("{id:?}");
}
}
Notes
The generated getter method matches each variant of the original enum and returns the corresponding variant of the ID enum. Ensure that the specified derive traits are in scope where the macro is used. The macro currently supports unit, tuple, and struct variants.
Dependencies
~1–8.5MB
~76K SLoC