4 releases
Uses old Rust 2015
0.1.7 | Aug 3, 2016 |
---|---|
0.1.3 | Dec 1, 2015 |
0.1.2 | Sep 16, 2015 |
0.1.1 | Aug 16, 2015 |
#1802 in Rust patterns
11,471 downloads per month
Used in 31 crates
(13 directly)
30KB
678 lines
This crate provides several macros for deriving some useful methods for unitary enums (i.e. enums where variants do not have payloads).
All of these macros are designed to be used with the custom_derive
crate, though they can be used independent of it.
Note: see also the
TryFrom!
macro provided by theconv
crate to derive a function for creating enum values from integer values.
Example
Derive iterators that yield all variants of an enum.
#[macro_use] extern crate custom_derive;
#[macro_use] extern crate enum_derive;
custom_derive! {
#[derive(Debug, PartialEq, Eq,
IterVariants(CandyVariants), IterVariantNames(CandyVariantNames))]
pub enum Candy { Musk, FruitRock, BoPeeps, LemonSherbert }
}
let vars: CandyVariants = Candy::iter_variants();
let names: CandyVariantNames = Candy::iter_variant_names();
assert_eq!(&*vars.zip(names).collect::<Vec<_>>(), &[
(Candy::Musk, "Musk"),
(Candy::FruitRock, "FruitRock"),
(Candy::BoPeeps, "BoPeeps"),
(Candy::LemonSherbert, "LemonSherbert"),
]);
Alternately, derive next_variant
and prev_variant
methods.
#[macro_use] extern crate custom_derive;
#[macro_use] extern crate enum_derive;
use Hanagami::*;
custom_derive! {
#[derive(Debug, PartialEq, Eq, NextVariant, PrevVariant)]
pub enum Hanagami { Sakigami, Hasugami, Tsutagami }
}
assert_eq!(Sakigami.next_variant(), Some(Hasugami));
assert_eq!(Hasugami.next_variant(), Some(Tsutagami));
assert_eq!(Tsutagami.next_variant(), None);
assert_eq!(Sakigami.prev_variant(), None);
assert_eq!(Hasugami.prev_variant(), Some(Sakigami));
assert_eq!(Tsutagami.prev_variant(), Some(Hasugami));
Overview
This crate provides macros to derive the following methods for unitary variant enums:
EnumDisplay
derivesDisplay
, which outputs the name of the variant. Note that for unitary variants, this is identical to the behaviour of a derivedDebug
implementation.EnumFromStr
derivesFromStr
, allowingstr::parse
to be used. It requires an exact match of the variant name.IterVariants
derivesiter_variants()
, which returns an iterator over the variants of the enum in lexical order.IterVariantNames
derivesiter_variant_names()
, which returns an iterator over the string names of the variants of the enum in lexical order.NextVariant
derivesnext_variant(&self)
, which returns the next variant, orNone
when called for the last.PrevVariant
derivesprev_variant(&self)
, which returns the previous variant, orNone
when called for the first.EnumFromInner
derivesFrom<T>
for each variant's payload, assuming all variants are unary.EnumInnerAsTrait
derives a method to return a borrowed pointer to the inner value, cast to a trait object.
Both of the IterVariant*
macros accept a single deriving form. Taking IterVariants
as an example, it must be invoked like so:
custom_derive! {
#[derive(IterVariants(GetVariants))]
pub enum Get { Up, Down, AllAround }
}
The argument is the name of the iterator type that will be generated. Neither macro imposes any naming requirements, save the obvious: the name must not conflict with any other types.
EnumInnerAsTrait
accepts a single deriving form that specifies the name of the method to be derived, whether the borrow should be mutable, and the trait of interest. For example:
custom_derive! {
#[derive(EnumInnerAsTrait(pub as_display -> &std::fmt::Display))]
enum Value {
U32(u32),
U64(u64),
}
}
let s = format!("{}", Value::U64(42).as_display());
assert_eq!(&s[..], "42");
The other macros take no arguments.
The methods and iterator types generated will be public if the enum itself is public; otherwise, they will be private.
Using Without custom_derive!
Although designed to be used with custom_derive!
, all of the macros in this crate can be used without it. The following:
custom_derive! {
#[derive(Copy, Clone, Debug, IterVariants(Vars))]
enum ItAintRight { BabeNo, NoNo, BoyBoy }
}
Can also be written as:
#[derive(Copy, Clone, Debug)]
enum ItAintRight { BabeNo, NoNo, BoyBoy }
IterVariants! { (Vars) enum ItAintRight { BabeNo, NoNo, BoyBoy } }
Other Examples
This shows how to use Display
and FromStr
to perform string round-tripping of enums.
#[macro_use] extern crate custom_derive;
#[macro_use] extern crate enum_derive;
custom_derive! {
#[derive(Debug, PartialEq, EnumDisplay, EnumFromStr)]
pub enum TrollDigit { One, Two, Three, Many, Lots }
}
fn to_troll(mut n: u32) -> String {
use std::fmt::Write;
let mut s = String::new();
if n == 0 {
panic!("I dun' see nuffin'; how's I s'posed to count it?!");
}
while n > 0 {
let (del, dig) = match n {
n if n >= 16 => (16, TrollDigit::Lots),
n if n >= 4 => (4, TrollDigit::Many),
n if n >= 3 => (3, TrollDigit::Three),
n if n >= 2 => (2, TrollDigit::Two),
_ => (1, TrollDigit::One),
};
n -= del;
if s.len() > 0 { s.push_str(" "); }
write!(&mut s, "{}", dig).unwrap();
}
s
}
fn from_troll(s: &str) -> Result<u32, enum_derive::ParseEnumError> {
let mut n = 0;
for word in s.split_whitespace() {
n += match try!(word.parse()) {
TrollDigit::One => 1,
TrollDigit::Two => 2,
TrollDigit::Three => 3,
TrollDigit::Many => 4,
TrollDigit::Lots => 16,
};
}
if n == 0 {
Err(enum_derive::ParseEnumError)
} else {
Ok(n)
}
}
let number = 42;
let troll_number = to_troll(number);
assert_eq!(troll_number, "Lots Lots Many Many Two");
assert_eq!(from_troll(&troll_number), Ok(number));