How do I get an enum as a string?

前端 未结 2 632
悲哀的现实
悲哀的现实 2020-12-18 17:41

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,
         


        
相关标签:
2条回答
  • 2020-12-18 18:15

    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.

    0 讨论(0)
  • 2020-12-18 18:27

    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");
    }
    
    0 讨论(0)
提交回复
热议问题