# Enumeration

## Defining an Enum

```rust
enum IpAddrKind {
  V4,
  V6
}

struct IpAddr {
  kind: IpAddrKind,
  address: String,
}

let home = IpAddr {
	kind: IpAddrKind::V4,
	address: String::from("127.0.0.1"),
};
```

We can also put data directly into each enum variant:

```rust
enum IpAddr {
	V4(String),
	V6(String),
}
let home = IpAddr::V4(String::from("127.0.0.1"));
let loopback = IpAddr::V6(String::from("::1"));
```

Each num variant we define also becomes a function that constructs an instance of the enum. That is, `IpAddr::V4()` is a function call that takes a `String` argument and returns an instance of the `IpAddr` type.

There’s another advantage to using an enum rather than a struct: each variant can have different types and amounts of associated data.

```rust
enum IpAddr {
	V4(u8, u8, u8, u8),
  V6(String),
}
```

Stand library way of defining:

```rust
struct Ipv4Addr {
    // --snip--
}

struct Ipv6Addr {
    // --snip--
}

enum IpAddr {
    V4(Ipv4Addr),
    V6(Ipv6Addr),
}
```

We can define method on enum using `impl`:

```rust
impl Message {
  fn call(&self) {
    // method body would be defined here
  }
}

left m = Message::Write(String::from("hello"));
m.call();
```

## The `Option` Enum and Its Advantages Over Null Values

The enum is defined by the standard library. The `Option` type encodes the very common scenario in which value could be something or it could be nothing.

Rust doesn’t have the null feature that many other languages have. *Null* is a value that means there is no value there. In languages with null, variables can always be in one of two states: null or not-null.

```rust
enum Option<T> {
  None,
  Some(T),
}
```

The `Option<T>` enum is so useful that it’s even included in the prelude. You can use `Some` and `None` directly without the `Option::` prefix.

```rust
let some_number = Some(5);
let some_char = Some('e');
let absent_number: Option<i32> = None;
```

Because `Option<T>` and `T` (where `T` can be any type) are different types, the compiler won’t let us use an `Option<T>` value as if it were definitely a valid value.

So a invalid number cannot take part in the calculation with a valid number.

## The `match` Control Flow Construct

```rust
fn value_in_cents(coin: Coin) -> u8 {
  match coin {
    Coin::Penny => {
      println("Lucky penny!");
      1
    } // the comma following the arm with curly braces is optional
    Coin::Nickel => 5,
    Coin::Dime => 10,
    Coin::Quater => 25,
  }
}
```

## Patterns That Bind to Values

```rust
enum UsState {
  Alabama,
  Alaska,
  //...
}

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::Quater(state) => {
          //do something to state
          25
      }
    }
}

```

```rust
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);
```

Matches in Rust are *exhaustive*: we must exhaust every last possibility in order for the code to be valid. Especially in the case of `Option<T>`.

## Catch-all Patterns and the \_ Placeholder

```rust
other => move_player(other)
_ => move_player
_ => () //the unint value
```

## Concise Control Flow with `if let`

We can think of `if let` as syntax sugar for a `match` that runs code when the value matches one pattern and then ignores all other values.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://osh.fducslg.com/notes/rust/enumeration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
