Is there a way to impl FromStr for an enum without additional fields data?

I have the below code:

#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
pub enum Type {
    #[default]
    FAKEDEFAULT,
    SENT {
        date_time: String,
        error: Option<String>,
    },
    ONE,
    TWO,
    THREE,
    FOUR,
    FIVE,
}

impl FromStr for Type {
    type Err = Error;

    fn from_str(o: &str) -> Result<Self, Self::Err> {
        match o {
            "FAKEDEFAULT" => Ok(Self::FAKEDEFAULT),
            "SENT" => Ok(Self::SENT(_)), // --> How to do this?
            "ONE" => Ok(Self::ONE),
            "TWO" => Ok(Self::TWO),
            "THREE" => Ok(Self::THREE),
            "FOUR" => Ok(Self::FOUR),
            "FIVE" => Ok(Self::FIVE),
            _ => Err(Error::with_context(format!("unknown Type: {o}"))),
        }
    }
}

I need this because I'm parsing that Type from a string and I would like to avoid another enum just for enum names without additional data (like date_time and error).

Is there a way?

Not exactly sure about your requirements, the string you receive and want to convert to Type does not contain the fields date_time and error serialised in some format, right? In that case, as long as all fields implement Default, I think the correct way would be to initialise the fields with their default value:

match o {
    "FAKEDEFAULT" => Ok(Self::FAKEDEFAULT),
    "SENT" => Ok(Self::SENT {
        date_time: Default::default(),
        error: Default::default(),
    }),
    "ONE" => Ok(Self::ONE),
    "TWO" => Ok(Self::TWO),
    "THREE" => Ok(Self::THREE),
    "FOUR" => Ok(Self::FOUR),
    "FIVE" => Ok(Self::FIVE),
    _ => Err(Error(format!("unknown Type: {o}"))),
}

Playground.

(struct update syntax unfortunately doesn't work for enum variants with structured fields, as I've learned today)

1 Like

Depends on you actual requirements, but most likely no. If you'll read the RFC 2363 you'll see that Servo had similar need and ended up not just going with two enums but with whole language extensions (stabilized in Rust 1.66).

In my experience people don't push and achieve language extension for something that have some easier solution.

Except, of course, if all your enum variants have suitable defaults. Then you may create correct, if empty, enum without doing that crazy dance with unsafe (read the blog post for explanation where and how unsafe is used in this scheme).

1 Like