Quick Note: Assigning Values to Enum Keys in Rust

"Quick Note" is my blog series which I keep quick logs of what I have learned today and document it. So, it naturally does not reflect the best practice.

We use enums to represent a case of type, of which we define there will be limited set of semantic values. The size of these values should naturally be more than two because we already have a type that represents this case, which is bool.

enums in Rust, though, are strange beasts. As I have said, enums are finite, see the obvious below:

// assuming you develop a game
enum GameState {
    MainMenuState,
    LoadingState,
    InGameState,
    PauseMenuState
}

These define the states of a game and GameState enum is limited to these four values. However, in Rust, you can also assing tuple or struct inside these values, see the same example in different shoes:

enum GameState {
    MainMenuState,
    LoadingState(f8),
    InGameState { level_file: String },
    PauseMenuState
}

This case is, well, interesting because that somehow finds a way to defy the principle of finite values of enums because not only the values of enums take a kind of constructor, but also the signatures of constructors might differ, which will lead to infinite amount of values. This case is obviously strange but had an advantage in the case of GameState.

Now, some of you might be wondering, "How do we assign some literal values to enum since it only accepts abstract types such as tuples and structs?".

I found a workaround for that. In the beginning, it feels somehow hackish but you get used to it in time. The first thing you need to know is that enum types can also be implemented (intended inline code block here). At first, let's define a new case that is suitable for this exact need.

enum Emoji {
    HappyFace,
    SadFace
}

While this simple enum is enough in definition, what we want is to get the related emoji from the selected enum value. In the language of aliens:

// we select a value from Emoji enum
let face = Emoji::HappyFace;

// we want...
let related_emoji = face.to_string(); // ...to have a `to_string` method on every value
println("{}", related_emoji);

How do we do that? Well, as I have said, we implement the to_string method:

enum Emoji {
    HappyFace,
    SadFace
}

impl Emoji {
    fn to_string(&self) -> String {
        match self { // this expression returns
            HappyFace => "😊".to_string(), // if HappyFace, will return this
            SadFace => "😢".to_string() // if SadFace, will return this
        }
    }
}

This is how we assign values to enum values.

Eray Erdin

Believing one day we will carry mobile oxygen tubes along and an umbrella which protects us from acidic rain under the cancer-distributing green sky.

Write your comment…

I see a similar pattern non localized where the value mapping is basically not implemented but 'resolved' by a static function. I think from a point of code cohesion your solution makes a lot of sense.

Reply to this…