Pattern-matching tagged unions in Rust

Have you ever looked for a way to pattern-match a certain type or value and wished you could extract additional data from each match (or case)? In C you can use unions for this, F# has discriminated unions and in C# you can use inheritance and reflection to achieve this. This post shows an example how to use enums with additional data and how to use them with pattern matching

Rustlang supports enums that look like this:

enum Endpoint {
    IP,
    IPAndPort
}

The enum has two values and it looks like one of them would indicate an IP-address and the other one an IP-address and port. In Rust you can actually store that data together with the enum like this:

enum Endpoint {
    IP(String),
    IPAndPort(String, i32)
}

Pattern matching in Rust

You can use the enum to create a variable and pattern-match on it like this:

e = Endpoint::IP(String::from("127.0.0.1"));

match e {
    Endpoint::IP(ip) => println!("Connecting to {} at default port", ip),
    Endpoint::IPAndPort(ip, port) => println!("Connecting to {}:{}", ip, port),
}

Complete example

enum Endpoint {
    IP(String),
    IPAndPort(String, i32)
}

fn match_address(endpoint: Endpoint) {
    match endpoint {
        Endpoint::IP(ip) => println!("Connecting to {} at default port", ip),
        Endpoint::IPAndPort(ip, port) => println!("Connecting to {}:{}", ip, port),
    }
}

fn main() {
    match_address(Endpoint::IP(String::from("127.0.0.1")));
    match_address(Endpoint::IPAndPort(String::from("127.0.0.1"), i32::from(8082)));
}

Output:

Connecting to 127.0.0.1 at default port
Connecting to 127.0.0.1:8082

For more info about tagged unions and its history, read this great article by Pat Shaughnessy

GrĂ¼sse aus Berlin!
Loek