Rust Enums in Structs

In Rust, structs can contain one or more enums. A struct is an object containing a collection of items with specified types. There are many options for data type of a struct’s items, including enums.

This means that the items inside a struct instance can have multiple values as specified by an enum.

How to Work With Enums in Structs

Working with enums inside structs is relatively simple but requires some care. There are a few things required:

  • An enum must be declared.
  • A struct must be declared.
  • The type of one or more of the items inside the struct can be the enum.
  • The struct must be instantiated, with the variant of the enum specified.

A struct declaration consists of key-value pairs consisting of each item name paired with its data type:

struct MyStruct{
    item1: EnumName,
    item2: i32,
    key3: String,
}

In order for a struct to contain an enum, the enum must be declared. The corresponding item in the struct references the enum itself, not a variant or instance.

enum EnumName {
    Variant1,
    Variant2,
    Variant3,
}

struct MyStruct{
    item1: EnumName,
    item2: i32,
    item3: String,
} 

let struct_instance = MyStruct {
    item1: Variant2,
    item2: 42,
    item3: String::from("Hello!"),
}

Example of Using an Enum Inside a Struct

Using enums inside structs gives us a great deal of power because it allows us to combine their features.

For example, if we are building a game then we may wish for characters to have a specific class such as Wizard or Warrior. We can use an enum to define a new data type that is either Wizard or Warrior. Then we can use that enum inside a struct that defines all of the character details like the character’s name, as well their role.

In the following code, we are creating characters for two players: Batman, who is a Warrior, and Dumbledore, who is a Wizard. These characters have three attributes: a name, a role (Warrior/Wizard), and they can move left or right.

The player characters are assembled using the Player struct, which contains two enums: Role and PlayerMove.

#![allow(dead_code)]

#[derive(Debug)]
enum Role {
    Wizard, Warrior,
}

#[derive(Debug)]
enum PlayerMove {
   Left, Right,
}

#[derive(Debug)]
struct Player {
    name: String,
    class: Role,
    turn: PlayerMove,
}

fn main() {
    let player1 = Player {
        name: String::from("Batman"),
        class: Role::Warrior,
        turn: PlayerMove::Left,
    };

    let player2 = Player {
        name: String::from("Dumbledore"),
        c:lass Role::Wizard,
        turn: PlayerMove::Right,
    };

    println!("{:?}", player1);
    println!("{:?}", player2);
}

Standard Output:

Player { name: "Batman", class: Warrior, turn: Left }
Player { name: "Dumbledore", class: Wizard, turn: Right }

Because we are using enums here, we have multiple options available inside the struct. A player can be either a Warrior or a Wizard, and can move Left or Right.