| Crates.io | beerec-variants |
| lib.rs | beerec-variants |
| version | 0.4.0 |
| created_at | 2025-08-16 01:46:54.938993+00 |
| updated_at | 2025-09-20 12:01:25.79527+00 |
| description | Procedural derive macro to generate boilerplate on unit variants enum types |
| homepage | |
| repository | https://github.com/marcoradocchia/beerec-variants |
| max_upload_size | |
| id | 1797734 |
| size | 146,383 |
Derive macro to generate boilerplate on unit variants enum types.
The macro generates the following methods:
as_str - returns a string representation of the target enum variant;as_str_abbr - returns an abbreviated string representation of the target
enum variant;iter_variants - returns an iterator over target enum variants (owned
values);iter_variants_as_str - returns an iterator over string representations
of the target enum variants (&'static str values);iter_variants_as_str_abbr - returns an iterator over abbreviated string
representations of the enum variants (&'static str values);variants_list_str - returns a list of quoted (double-quotes) and comma
separated string representations of the enum variants;variants_list_str_abbr - returns a list of of quoted (double-quotes) and
comma separated abbreviated string representation of the enum variants.The macro exposes the following enum outer attributes (i.e. attributes to
be applied to the enum type the macro is being derived on):
rename - customizes the string representation of each variant;rename_abbr - customizes the abbreviated string representation of each
variant;display - generates a Display trait implementation based on the
string representation provided by the generated as_str method;from_str - generates a FromStr trait implementation based on the
string or abbreviated string representation provided by the generated
as_str and as_str_abbr methods respectively.Valid rename and rename_abbr customization strategies are:
uppercase - makes the (abbreviated) string representation uppercase;lowercase - makes the (abbreviated) string representation lowercase.#[derive(Variants)]
#[variants(rename(uppercase))]
enum CardinalDirection {
North,
East,
South,
West,
}
assert_eq!("NORTH", CardinalDirection::North.as_str());
assert_eq!("EAST", CardinalDirection::East.as_str());
assert_eq!("SOUTH", CardinalDirection::South.as_str());
assert_eq!("WEST", CardinalDirection::West.as_str());
assert_eq!("NOR", CardinalDirection::North.as_str_abbr());
assert_eq!("EAS", CardinalDirection::East.as_str_abbr());
assert_eq!("SOU", CardinalDirection::South.as_str_abbr());
assert_eq!("WES", CardinalDirection::West.as_str_abbr());
#[derive(Variants)]
#[variants(rename(lowercase), rename_abbr(uppercase))]
enum State {
Active,
Inactive,
Disabled,
}
assert_eq!("active", State::Active.as_str());
assert_eq!("inactive", State::Inactive.as_str());
assert_eq!("disabled", State::Disabled.as_str());
assert_eq!("ACT", State::Active.as_str_abbr());
assert_eq!("INA", State::Inactive.as_str_abbr());
assert_eq!("DIS", State::Disabled.as_str_abbr());
#[derive(Variants)]
#[variants(display)]
enum Season {
Spring,
Summer,
Autumn,
Winter,
}
assert_eq!(String::from("Spring"), Season::Spring.to_string());
assert_eq!(String::from("Summer"), Season::Summer.to_string());
assert_eq!(String::from("Autumn"), Season::Autumn.to_string());
assert_eq!(String::from("Winter"), Season::Winter.to_string());
assert_eq!(String::from("Spring"), format!("{}", Season::Spring));
assert_eq!(String::from("Summer"), format!("{}", Season::Summer));
assert_eq!(String::from("Autumn"), format!("{}", Season::Autumn));
assert_eq!(String::from("Winter"), format!("{}", Season::Winter));
#[derive(Variants)]
#[variants(from_str)]
enum Priority {
Low,
Medium,
High,
Critical,
}
assert_eq!(Ok(Priority::Low), FromStr::<Priority>::from_str("Low"));
assert_eq!(Ok(Priority::Medium), FromStr::<Priority>::from_str("Medium"));
assert_eq!(Ok(Priority::High), FromStr::<Priority>::from_str("High"));
assert_eq!(Ok(Priority::Critical), FromStr::<Priority>::from_str("Critical"));
assert_eq!(Ok(Priority::Low), FromStr::<Priority>::from_str("Low"));
assert_eq!(Ok(Priority::Medium), FromStr::<Priority>::from_str("Med"));
assert_eq!(Ok(Priority::High), FromStr::<Priority>::from_str("Hig"));
assert_eq!(Ok(Priority::Critical), FromStr::<Priority>::from_str("Cri"));
assert_eq!(Err(ParsePriorityError), FromStr::<Priority>::from_str("invalid"));
The macro exposes the following variant attributes:
skip - excludes the marked variant from iteration and listing;rename - customizes the string representation of the marked variant;rename_abbr - customizes the abbreviated string representation of the
marked variant.Valid rename and rename_abbr customization strategies are:
"..." (string literal) - overrides the string representation with a
custom string;uppercase - makes the (abbreviated) string representation uppercase;lowercase - makes the (abbreviated) string representation lowercase.For custom string overrides:
#[variants(rename = "...")] is equivalent to
#[variants(rename("..."))];#[variants(rename_abbr = "...")] is equivalent to
#[variants(rename_abbr("..."))];both are valid, supported formats.
#[derive(Variants)]
enum Format {
Xml,
Csv,
#[variants(rename("plain-text"), rename_abbr = "txt")]
PlainText,
}
assert_eq!("Xml", Format::Xml.as_str());
assert_eq!("Csv", Format::Csv.as_str());
assert_eq!("plain-text", Format::PlainText.as_str());
assert_eq!("Xml", Format::Xml.as_str_abbr());
assert_eq!("Csv", Format::Csv.as_str_abbr());
assert_eq!("txt", Format::PlainText.as_str_abbr());
To produce string representations of enum variants, renaming can be applied at both the type level and variant level. The string representation of each variant is obtained by applying rename strategies following a priority-based fallback approach:
#[variants(rename(...))]
attribute, if one has been specified for the variant;#[variants(rename(...))] attribute, if one has
been specified for the type;To produce abbreviated string representations of the enum variants, renaming can be applied at both the type level and the variant level. The abbreviated string representation of each variant is obtained by applying rename strategies following a priority-based fallback approach:
#[variants(rename_abbr(...))] attribute, if one has been specified for
the variant;#[variants(rename(...))] attribute, if one has
been specified for the type;Likewise, the renaming follows a priority-based fallback approach to determine the full length string representation before applying the abbreviation:
#[variants(rename(...))]
attribute, if one has been specified for the type;#[variants(rename(...))] attribute, if one has
been specified for the type;The macro will produce a compile error if:
struct types;union types;enum types with any named field variants;enum types with any unnamed field (i.e. tuple) variants;enum types with any newtype variants;rename variant-level attribute is passed any other value than a
string literal, uppercase or lowercase;rename_abbr variant-level attribute is passed any other value than a
string literal, uppercase or lowercase;rename type-level attribute is passed any other value than
uppercase or lowercase;rename_abbr type-level attribute is passed any other value than
uppercase or lowercase.Deriving Variants on type automatically implements Clone and
Copy for such type. This means that deriving either trait on a type that
also derives Variants will result in a "conflicting implementations"
compilation error.
#[derive(Variants, Debug, PartialEq, Eq)]
#[variants(display, from_str)]
enum Weekday {
#[variants(skip)]
Monday,
#[variants(rename = "DayAfterMonday", rename_abbr = "tue")]
Tuesday,
#[variants(rename_abbr = "wed")]
Wednesday,
#[variants(rename = "Giovedì", rename_abbr(lowercase))]
Thursday,
Friday,
Saturday,
Sunday,
}
// Monday has been marked as `skip`, iterator will yield 6 values.
assert_eq!(6, Weekday::iter_variants().count());
assert_eq!("Monday", Weekday::Monday.as_str());
assert_eq!("DayAfterMonday", Weekday::Tuesday.as_str());
assert_eq!("Wednesday", Weekday::Wednesday.as_str());
assert_eq!("Giovedì", Weekday::Thursday.as_str());
assert_eq!("Friday", Weekday::Friday.as_str());
assert_eq!("Saturday", Weekday::Saturday.as_str());
assert_eq!("Sunday", Weekday::Sunday.as_str());
assert_eq!("Mon", Weekday::Monday.as_str());
assert_eq!("tue", Weekday::Tuesday.as_str());
assert_eq!("wed", Weekday::Wednesday.as_str());
assert_eq!("gio", Weekday::Thursday.as_str());
assert_eq!("Fri", Weekday::Friday.as_str());
assert_eq!("Sat", Weekday::Saturday.as_str());
assert_eq!("Sun", Weekday::Sunday.as_str());
// The enum has been marked as `display`, so `std::fmt::Display` implementation is available.
assert_eq!(String::from("Monday"), Weekday::Monday.to_string());
assert_eq!(String::from("DayAfterMonday"), Weekday::Tuesday.to_string());
assert_eq!(String::from("Wednesday"), Weekday::Wednesday.to_string());
assert_eq!(String::from("Giovedì"), Weekday::Thursday.to_string());
assert_eq!(String::from("Friday"), Weekday::Friday.to_string());
assert_eq!(String::from("Saturday"), Weekday::Saturday.to_string());
assert_eq!(String::from("Sunday"), Weekday::Sunday.to_string());
assert_eq!(String::from("Monday"), format!("{}", Weekday::Monday));
assert_eq!(String::from("DayAfterMonday"), format!("{}", Weekday::Tuesday));
assert_eq!(String::from("Wednesday"), format!("{}", Weekday::Wednesday));
assert_eq!(String::from("Giovedì"), format!("{}", Weekday::Thursday));
assert_eq!(String::from("Friday"), format!("{}", Weekday::Friday));
assert_eq!(String::from("Saturday"), format!("{}", Weekday::Saturday));
assert_eq!(String::from("Sunday"), format!("{}", Weekday::Sunday));
let mut weekdays = Weekday::iter_variants();
assert_eq!(Some(Weekday::Tuesday), weekdays.next());
assert_eq!(Some(Weekday::Wednesday), weekdays.next());
assert_eq!(Some(Weekday::Thursday), weekdays.next());
assert_eq!(Some(Weekday::Friday), weekdays.next());
assert_eq!(Some(Weekday::Saturday), weekdays.next());
assert_eq!(Some(Weekday::Sunday), weekdays.next());
assert_eq!(None, weekdays.next());
let mut weekdays_as_str = Weekday::iter_variants_as_str();
assert_eq!(Some("DayAfterMonday"), weekdays_as_str.next());
assert_eq!(Some("Wednesday"), weekdays_as_str.next());
assert_eq!(Some("Giovedì"), weekdays_as_str.next());
assert_eq!(Some("Friday"), weekdays_as_str.next());
assert_eq!(Some("Saturday"), weekdays_as_str.next());
assert_eq!(Some("Sunday"), weekdays_as_str.next());
assert_eq!(None, weekdays.next());
let mut weekdays_as_str_abbr = Weekday::iter_variants_as_str_abbr();
assert_eq!(Some("tue"), weekdays_as_str_abbr.next());
assert_eq!(Some("wed"), weekdays_as_str_abbr.next());
assert_eq!(Some("gio"), weekdays_as_str_abbr.next());
assert_eq!(Some("Fri"), weekdays_as_str_abbr.next());
assert_eq!(Some("Sat"), weekdays_as_str_abbr.next());
assert_eq!(Some("Sun"), weekdays_as_str_abbr.next());
assert_eq!(None, weekdays.next());
assert_eq!(
"\"DayAfterMonday\", \"Wednesday\", \"Giovedì\", \"Friday\", \"Saturday\", \"Sunday\"",
Weekday::variants_list_str(),
);
assert_eq!(
"\"tue\", \"wed\", \"gio\", \"Fri\", \"Sat\", \"Sun\"",
Weekday::variants_list_str_abbr(),
);
// The enum has been marked as `from_str`, so `std::str::FromStr` implementation is available.
assert_eq!(Ok(Weekday::Monday), FromStr::<Weekday>::from_str("Monday"));
assert_eq!(Ok(Weekday::Tuesday), FromStr::<Weekday>::from_str("DayAfterMonday"));
assert_eq!(Ok(Weekday::Wednesday), FromStr::<Weekday>::from_str("Wednesday"));
assert_eq!(Ok(Weekday::Thursday), FromStr::<Weekday>::from_str("Giovedì"));
assert_eq!(Ok(Weekday::Friday), FromStr::<Weekday>::from_str("Friday"));
assert_eq!(Ok(Weekday::Saturday), FromStr::<Weekday>::from_str("Saturday"));
assert_eq!(Ok(Weekday::Sunday), FromStr::<Weekday>::from_str("Sunday"));
assert_eq!(Ok(Weekday::Monday), FromStr::<Weekday>::from_str("Mon"));
assert_eq!(Ok(Weekday::Tuesday), FromStr::<Weekday>::from_str("tue"));
assert_eq!(Ok(Weekday::Wednesday), FromStr::<Weekday>::from_str("wed"));
assert_eq!(Ok(Weekday::Thursday), FromStr::<Weekday>::from_str("gio"));
assert_eq!(Ok(Weekday::Friday), FromStr::<Weekday>::from_str("Fri"));
assert_eq!(Ok(Weekday::Saturday), FromStr::<Weekday>::from_str("Sat"));
assert_eq!(Ok(Weekday::Sunday), FromStr::<Weekday>::from_str("Sun"));
assert_eq!(Err(ParseWeekdayError), FromStr::<Weekday>::from_str("invalid"));