Structs and Enums in Rust
Tags: beginners, programming, rust, learning
Published: 2023-07-12 13:46:56

Rust is a powerful systems programming language that has been rapidly gaining popularity among developers. One of the reasons for its success is its rich type system, which provides a high level of expressiveness and flexibility when defining custom data types. Two of the most important constructs in Rust’s type system are structures (`struct`) and enumerations (`enum`), which allow developers to create complex data types that accurately model the problem domain.

In this blog post, we will take a deep dive into `struct` and `enum` in Rust, exploring their syntax, usage, and best practices. We will learn how to use these constructs to create expressive and efficient code that is easy to read, understand, and maintain. Whether you’re new to Rust or an experienced developer looking to deepen your understanding of the language, this post is for you! So grab a cup of coffee and let’s get started on our journey to mastering `struct` and `enum` in Rust!

## Understanding Structs

Structs are a way to define custom data types in Rust. They allow you to group related data together into a single, cohesive unit. Structs are similar to classes in other languages, but with some important differences.

Let’s say we’re creating a Mario game and we want to represent Mario as a character in our game. We could use a `struct` to define a `Mario` type like this:

```rust
struct Position {
    x: u32,
    y: u32
}

struct Mario {
    position: Position,
    coins: u32,
    power_up: Option<PowerUp>,
}
```

In this example, we’ve defined a `Mario` struct with three fields: `position`, `coins`, and `power_up`. The `position` field is of type `Position`, which we defined earlier. The `coins` field is of type `u32`, representing the number of coins Mario has collected. The `power_up` field is of type `Option<PowerUp>`, representing an optional power-up that Mario may have. We will discuss this type later when we come to Enums.

To create an instance of this struct, we can use the following syntax:

```rust
let mario = Mario {
    position: Position { x: 0, y: 0 },
    coins: 0,
    power_up: None,
};
```

We can access the fields of a struct using dot notation, like this:

```rust
let pos = mario.position;
let coins = mario.coins;
let power_up = mario.power_up;
```

Structs can also have methods, which are functions associated with the struct. Here’s an example of how to define a method for our `Mario` struct:

```rust
impl Mario {
    fn jump(&mut self) {
        self.position.y += 1;
        if let Some(power_up) = self.power_up {
            match power_up {
                PowerUp::SuperMushroom => self.position.y += 1,
                PowerUp::FireFlower => self.position.y += 2,
            }
        }
    }
}
```

In this example, we’ve defined a method called `jump` that makes Mario jump. The height of the jump depends on whether Mario has a power-up and what type of power-up it is. To call this method, we can use the following syntax:

```rust
mario.jump();
```

As you can see, structs are a powerful way to define custom data types in Rust. They allow you to group related data together and provide methods for working with that data. In the next section, we’ll explore another important construct in Rust’s type system: `enums`.

## Enum1, Enum2, Enum3

Enums, short for enumerations, are another way to define custom data types in Rust. They allow you to define a type with a fixed set of values, known as variants. Enums are useful when you need to represent a value that can be one of several different options.

Let’s say we want to represent the different power-ups that Mario can have in our game. We could use an `enum` to define a `PowerUp` type like this:

```rust
enum PowerUp {
    SuperMushroom,
    FireFlower,
    Starman,
    CapeFeather,
}
```

In this example, we’ve defined an `enum` called `PowerUp` with four variants: `SuperMushroom`, `FireFlower`, `Starman`, and `CapeFeather`. Each variant represents a different type of power-up that Mario can have.

To create an instance of this enum, we can use the following syntax:

```rust
let power_up = PowerUp::SuperMushroom;
```

We can use pattern matching to check which variant an enum value is. Here’s an example of how to do this:

```rust
match power_up {
    PowerUp::SuperMushroom => println!("Mario got a Super Mushroom!"),
    PowerUp::FireFlower => println!("Mario got a Fire Flower!"),
    PowerUp::Starman => println!("Mario got a Starman!"),
    PowerUp::CapeFeather => println!("Mario got a Cape Feather!"),
}
```

In this example, we’re using a `match` expression to check which variant the `power_up` value is. Depending on the variant, we print a different message to the screen.

As you can see, enums allow you to represent values that can be one of several different options and provide an expressive way to work with those values. In the next section, we’ll explore how enums and structs can be combined to create even more complex data types.

## Combining both our super powers! Structs and Enums

Structs and enums are powerful constructs on their own, but they can be even more powerful when combined. By using enums to group related structs or adding a field to a struct that is an enum type, you can create complex data types that accurately model your problem domain.

Say we want to represent the different enemies that Mario can encounter in our game. We could use an `enum` to define an `Enemy` type like this:

```rust
enum Enemy {
    Goomba(Goomba),
    KoopaTroopa(KoopaTroopa),
    HammerBro(HammerBro),
}
```

In this example, we’ve defined an `enum` called `Enemy` with three variants: `Goomba`, `KoopaTroopa`, and `HammerBro`. Each variant is associated with a different struct that represents the specific type of enemy.

Here’s what the `Goomba` struct might look like:

```rust
struct Goomba {
    position: Position,
    is_stomped: bool,
}
```

And here’s what the `KoopaTroopa` struct might look like:

```rust
struct KoopaTroopa {
    position: Position,
    is_stomped: bool,
    is_in_shell: bool,
}
```

By using an enum to group these related structs together, we can create a single `Enemy` type that can represent any of the different types of enemies in our game. This makes it easy to write code that can work with any type of enemy, without having to worry about the specific details of each enemy type.

Here’s an example of how we might use this `Enemy` enum in our code:

```rust
fn stomp_enemy(enemy: &mut Enemy) {
    match enemy {
        Enemy::Goomba(goomba) => goomba.is_stomped = true,
        Enemy::KoopaTroopa(koopa) => {
            koopa.is_stomped = true;
            koopa.is_in_shell = true;
        }
        Enemy::HammerBro(_) => {}
    }
}
```

In this example, we’ve defined a function called `stomp_enemy` that takes an `Enemy` as an argument and stomps on it. The behavior of the function depends on which variant of the `Enemy` enum is passed in. If it’s a `Goomba`, we set its `is_stomped` field to `true`. If it’s a `KoopaTroopa`, we set both its `is_stomped` and `is_in_shell` fields to `true`. If it’s a `HammerBro`, we don’t do anything.

Combining structs and enums allows us to create complex data types that accurately model our problem domain. By using enums to group related structs together, we can write code that is expressive, flexible, and easy to understand.

## Conclusion

In conclusion, `struct` and `enum` are two powerful constructs in Rust's type system that allow developers to define custom data types. Structs are used to group related data together into a single unit, while enums are used to define types with a fixed set of values. By combining structs and enums, developers can create complex data types that accurately model their problem domain.

In this blog post, we've explored the syntax and usage of `struct` and `enum` in Rust, providing examples and best practices along the way. We've also seen how these constructs can be combined to create even more powerful data types. Whether you're new to Rust or an experienced developer, we hope this post has deepened your understanding of these important features of the language.

## About me

I’m a software engineer and a tech blogger with a passion for writing about the latest developments in the world of technology. I have experience working with a variety of programming languages, including Python, TypeScript, Rust, and Go, and I love sharing my knowledge and insights with others.

When I’m not coding or writing, you can find me exploring the great outdoors, making art. I’m a digital artist who enjoys drawing and painting.

I’m always looking to connect with other tech enthusiasts and artists, so feel free to reach out to me on my socials!

### You can find me on:

Twitter: https://twitter.com/SonuBardai

LinkedIn: https://www.linkedin.com/mwlite/in/sonu-bardai

GitHub: https://github.com/SonuBardai

Personal Website: https://sonubardai-portfolio.web.app

Thanks for stopping by, and I hope you enjoyed my blog! Happy coding! 😊