---
date: 2020-09-02
id: b95f09af-2cd0-46f2-872e-3cb542d2b2e9
title: Rust enums
---

# Basics

Rust also supports
[enums](https://doc.rust-lang.org/rust-by-example/custom_types/enum.html).

``` rust
use std::fmt::Debug;

#[derive(Debug)]
enum Message {
    Write(String),
}

fn main() {
    let m = Message::Write(String::from("Hello!"));
    println!("{:?}", m)
}
```

# Methods

As with [structs](20200831193417-structs), methods can be defined as
well:

``` rust
use std::fmt::Debug;

#[derive(Debug)]
enum Message {
    Write(String),
}

impl Message {
    fn call(&self) {
        println!("tralala");
        println!("{:?}", self)
    }
}

fn main() {
    let m = Message::Write(String::from("Hello!"));
    m.call();
}
```

# Standard library enums

## Option

Instead of \`null\` Rust has the
[Option](https://doc.rust-lang.org/std/option/enum.Option.html) enum
built in:

``` rust
fn main() {
    let some_number = Some(5);
    let some_string = Some("a string");

    let absent_number: Option<i32> = None;
}
```

The cool thing about using Option is that \`Option\<T\>\` and \`T\` are
different types, therefore the programmer has to define if NULL is
acceptable beforehand. The following won't run:

``` rust
fn main() {
    let x: i8 = 5;
    let y: Option<i8> = Some(5);

    let sum = x + y;
}
```

Huzzah, No more having to worry about incorrectly assuming a not null
value!

# Match control flow operator

Think of \`switch\`, but for enums.

``` rust
enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => {
            println!("Lucky penny!");
            1
        }
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}

fn main() {}
```

## Patterns that bind to values

Another useful feature of match arms is that they can bind to the parts
of the values that match the pattern. This is how we can extract values
out of enum variants.

``` rust
#[derive(Debug)]
enum UsState {
    Alabama,
    Alaska,
    // --snip--
}

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter(state) => {
            println!("State quarter from {:?}!", state);
            25
        }
    }
}

fn main() {
    value_in_cents(Coin::Quarter(UsState::Alaska));
}
```

## Matching with Option\<T\>

\`match\` also plays nice with \`Option\<t\>\`:

``` rust
fn main() {
    fn plus_one(x: Option<i32>) -> Option<i32> {
        match x {
            None => None,
            Some(i) => Some(i + 1),
        }
    }

    let five = Some(5);
    let six = plus_one(five);
    let none = plus_one(None);
}
```

## The \_ Placeholder

Rust also has a pattern we can use when we don’t want to list all
possible values:

``` rust
fn main() {
    let some_u8_value = 0u8;
    match some_u8_value {
        1 => println!("one"),
        3 => println!("three"),
        5 => println!("five"),
        7 => println!("seven"),
        _ => (),
    }
}
```

## if let syntax suger

``` rust
fn main() {
    let some_u8_value = Some(0u8);
    match some_u8_value {
        Some(3) => println!("three"),
        _ => (),
    }
}
```

is the same as

``` rust
fn main() {
    let some_u8_value = Some(0u8);
    if let Some(3) = some_u8_value {
        println!("three");
    }
}
```

and

``` rust
#[derive(Debug)]
enum UsState {
    Alabama,
    Alaska,
    // --snip--
}

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}

fn main() {
    let coin = Coin::Penny;
    let mut count = 0;
    match coin {
        Coin::Quarter(state) => println!("State quarter from {:?}!", state),
        _ => count += 1,
    }
}
```

is the same as

``` rust
#[derive(Debug)]
enum UsState {
    Alabama,
    Alaska,
    // --snip--
}

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}

fn main() {
    let coin = Coin::Penny;
    let mut count = 0;
    if let Coin::Quarter(state) = coin {
        println!("State quarter from {:?}!", state);
    } else {
        count += 1;
    }
}
```
