I have an enum with many values and I'd like to write the name of one of its values to a stream:
enum Foo {
Bar = 0x00,
Baz = 0x01,
Qux = 0x02,
// ...
Quux = 0xFF,
}
I can derive Debug
and do
writer.write(format!("I am {:?}", Foo::Quux).as_bytes())
which will output e.g. I am Quux
. That's fine, except that
Debug
isn't appropriateThere are two ways to convert an Enum to String in Java, first by using the name() method of Enum which is an implicit method and available to all Enum, and second by using toString() method.
You can't. I think you have FOUR options here. All four offer a solution but with a slightly different approach... Option One: use the built-in name() on an enum.
Before you learn about enum strings, make sure to know about Java enum. In the above example, we have seen the default string representation of an enum constant is the name of the same constant.
Since the names of enum variants are fixed, you don't need to allocate a String
, a &'static str
will suffice. A macro can remove the boilerplate:
macro_rules! enum_str {
(enum $name:ident {
$($variant:ident = $val:expr),*,
}) => {
enum $name {
$($variant = $val),*
}
impl $name {
fn name(&self) -> &'static str {
match self {
$($name::$variant => stringify!($variant)),*
}
}
}
};
}
enum_str! {
enum Foo {
Bar = 0x00,
Baz = 0x01,
Qux = 0x02,
//...
Quux = 0xFF,
}
}
fn main() {
assert_eq!(Foo::Baz.name(), "Baz");
}
Even better, you can derive these with a crate like strum_macros.
In strum 0.10, you can use AsStaticRef
/ AsStaticStr
to do the exact same code:
extern crate strum; // 0.10.0
#[macro_use]
extern crate strum_macros; // 0.10.0
use strum::AsStaticRef;
#[derive(AsStaticStr)]
enum Foo {
Bar = 0x00,
Baz = 0x01,
Qux = 0x02,
//...
Quux = 0xFF,
}
fn main() {
assert_eq!(Foo::Baz.as_static(), "Baz");
}
In strum 0.9, the string slice's lifetime is not 'static
in this case:
#[macro_use]
extern crate strum_macros; // 0.9.0
#[derive(AsRefStr)]
enum Foo {
Bar = 0x00,
Baz = 0x01,
Qux = 0x02,
//...
Quux = 0xFF,
}
fn main() {
assert_eq!(Foo::Baz.as_ref(), "Baz");
}
Probably the easiest way would be to implement Display
by calling into Debug
:
impl fmt::Display for Foo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
// or, alternatively:
// fmt::Debug::fmt(self, f)
}
}
Then you can use to_string()
to get a String
representation:
let s: String = Foo::Quux.to_string();
If you have many enums which you want to print, you can write a trivial macro to generate the above implementation of Display
for each of them.
Unfortunately, in Rust reflective programming is somewhat difficult. There is no standard way, for example, to get a list of all variants of a C-like enum. Almost always you have to abstract the boilerplate with custom-written macros (or finding something on crates.io). Maybe this will change in future if someone would write an RFC and it would get accepted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With