Noob: enum <= String with symbols - resolved

Why can I not do something like this?

pub enum MediaType { json = "application/json" }
pub enum MediaType2 { "application/json" }

The symbol / throws error, which is why I tried putting it to a String.
I've tried a number of variants, expecting there must be a way for enum to hold instances of base types.

Surely enum is in essence a ProperNoun and so should accept all kinds of names of base thing?

I'm not sure what you want to do, but if you want an enum variant with a String in it, you can do this:

pub enum MyType {
    MyVariant(String),
}

// And asign it when creating one:
let my_var = MyType::MyVariant("hello world".to_owned());

If what you want is a type-safe representation of a string, that can be converted to an actual string, you can use this:

pub enum MediaType {
    ApplicationJson,
}

impl MediaType {
    pub fn as_str(&self) -> &'static str {
        match *self {
            MediaType::ApplicationJson => "application/json",
        }
    }
}
5 Likes

You can also use constants but I recommend using an enum as @Razican suggested.

pub mod media_type {
    pub const JSON: &'static str = "application/json";
    pub const TEXT: &'static str = "text/plain";
}
1 Like

I'm pretty sure what you want is @Razican's second example. Enums in Rust don't work quite like they do in some other languages, and I think your mental model is a little askew.

If you have an enum like this in Rust:

pub enum MediaType {
    PlainText,
    ApplicationJson,
    ImageJpeg,
    ImagePng,
    ...
}

Each of these is called a variant. Variants can carry data, but this is very different from what you wanted to do, which was represent the variant itself as some kind of string. In a low level language like Rust, representing each variant as a string would not work, because each variant's string, being of a different length, takes up a different amount of bytes.

In Rust, an enum like this one is represented similar to how an integer would be represented, and each variant is assigned to a single integer value. This works because a machine integer takes up a specified number of bits (i32 vs i8, for example), so every variant has the same size.

If you want to be able to convert your enum to a string - for display purposes, for example - you need to implement a method like the one in @Razican's post.

1 Like

If you want to associate a str with each enum variant, you'll probably need to do something like this:

pub enum MediaType {
    PlainText,
    ApplicationJson,
}

impl MediaType {
    pub fn from_str(s: &str) -> Option<MediaType> {
        match s {
            "text/plain" => Some(MediaType::PlainText),
            "application/json" => Some(MediaType::ApplicationJson),
            _ => None,
        }
    }

    pub fn as_str(&self) -> &'static str {
        match s {
            MediaType::PlainText => "text/plain",
            MediaType::ApplicationJson => "application/json",
        }
    }
}
4 Likes

Thanks - that's very clear.

I'm just looking to tie up the boundary of what is declared and expecting then that base types can be made. Above does that well I think.

I think that in the case of from_str() it would be better to use the FromStr trait. That way it can be used woth the parse() method in String.

    pub fn as_str(&self) -> &'static str {
        match s {
            MediaType::PlainText => "text/plain",
            MediaType::ApplicationJson => "application/json",
        }
    }