Pattern matching
Enum variants can optionally include payloads.
enum Color {
    Green,
    Yellow,
    Red,
    Custom { red: u8, green: u8, blue: u8 }
}
let green: Color = Color::Green;
let yellow: Color = Color::Yellow;
let red: Color = Color::Red;
let blue: Color = Color::Custom { red: 0, green: 0, blue: 255 };
Here, the Red, Yellow, and Green variants work about the same way as before.
The Custom variant has a built-in struct with three u8 fields. We must
specify those fields when constructing a Color::Custom variant, and we can
deconstruct them in a match to read their values.
match current_color {
    Color::Green => {
        println!("green");
    }
    Color::Yellow => {
        println!("yellow");
    }
    Color::Custom { red, green, blue } => {
        println!("custom (RGB {}, {}, {})", red, green, blue);
    }
}
This is known as pattern matching. Each of the conditions before a =>
arrow is called a pattern, and at runtime Rust will try checking each
pattern in turn to see which one matches. The first time it finds a match,
it will run the corresponding code and then exit the match.
Matching multiple variants
You can match on a variant multiple times.
match current_color {
    Color::Green => {
        println!("green");
    }
    Color::Custom { red: 0, green, blue } => {
        println!("custom color with no red (RGB 0, {}, {})", green, blue);
    }
    Color::Custom { red, green, blue } => {
        println!("custom (RGB {}, {}, {})", red, green, blue);
    }
}
Tuple payloads
If you don't want to name the fields in a payload, you can use a tuple payload:
enum Color {
    Green,
    Yellow,
    Red,
    Custom(u8, u8, u8)
}
In that case, when pattern matching on them, use a similar syntx to destructure the tuple payload:
match current_color {
    Color::Green => {
        println!("green");
    }
    Color::Yellow => {
        println!("yellow");
    }
    Color::Red => {
        println!("red");
    }
    Color::Custom(red, green, blue) => {
        println!("custom (RGB {}, {}, {})", red, green, blue);
    }
}
Runtime representation
As previously discussed, this enum would be a u8 at runtime.
enum Color {
    Green,
    Yellow,
    Red,
    Custom
}
Green would be 0 at runtime, Yellow would be 1, Red would be 2, and
Custom would be 3. If we introduce a payload, things change:
enum Color {
    Green,
    Yellow,
    Red,
    Custom(u8, u8, u8)
}
Now, Color::Custom has a runtime representation of four u8 values. The 
first u8 holds the number 4, just like before. That's the value that match 
examines at runtime to be able to tell which variant this is, and we call that
value "thetdiscriminant." The other three u8 values are its payload.
This means that a Color::Custom variant takes up 4 bytes at runtime: one byte
for the u8 discriminant, and three more bytes for its (u8, u8, u8) payload.
A rule of enums is that each variant always takes up exactly the same amount 
of memory, no matter what's in it. This means that because Color::Custom takes
up 4 bytes at runtime, so do Color::Green, Color::Yellow, and Color::Red,
even though they don't have payloads. Those variants consist of a u8 
discriminant followed by three bytes of unused memory.
This is necessary because Rust has to know at compile time exactly how much memory to allocate for every value. Consider this function:
fn color_to_string(color: Color, max_string_length: u32) -> String
Rust needs to know how much memory, to reserve for the Color argument, but
it can't know ahead of time what variant will go in there. This function could
be called with any Color variant. To support all the variants, it needs to
have room for the largest variant, so the largest variant ends up determining
the size of all the variants. (This is true in other situations too, not just
function arguments.)
This has implications for performance: increasing the size of the largest variant in an enum increases the size of all the others as well, but increasing the size of a variant that isn't the largest has no effect on the sizes of any other variants.