Search code examples
stringrustenumscoercion

Can I declare an enum value that takes a String or &str without needing additional functions?


I have an enum with a String:

enum MyLovelyEnum {
    Thing(String),
}

For tests, I would like to be able to pass in a &'static str to avoid MyLovelyEnum::Thing("abc".to_string) over and over.

I found that you can do this nicely with structs with a constructor:

// From: https://hermanradtke.com/2015/05/06/creating-a-rust-function-that-accepts-string-or-str.html
struct Person {
    name: String,
}

impl Person {
    fn new<S: Into<String>>(name: S) -> Person {
        Person { name: name.into() }
    }
}

fn main() {
    let person = Person::new("Herman");
    let person = Person::new("Herman".to_string());
}

I know I can use lifetimes or Cow as described in What's the best practice for str/String values in Rust enums? or I can make my own function.

Is there something close to the example in the blog post for enums? e.g.

// this is the kind of thing I am after but this specifically is not correct syntax
enum MyLovelyEnum {
  Thing<S: Into<String>>(S)
}

Solution

  • You can create a generic enum:

    enum MyLovelyEnum<S>
    where
        S: Into<String>,
    {
        Thing(S),
    }
    
    MyLovelyEnum::Thing("a");
    MyLovelyEnum::Thing("b".to_string());
    

    I likely wouldn't do that in my code, instead opting to create a constructor, much like the blog post you linked:

    enum MyLovelyEnum {
        Thing(String),
    }
    
    impl MyLovelyEnum {
        fn thing(s: impl Into<String>) -> Self {
            MyLovelyEnum::Thing(s.into())
        }
    }
    
    MyLovelyEnum::thing("a");
    MyLovelyEnum::thing("b".to_string());