Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I match a String in a struct with a constant value?

Is it possible to match against a String in a struct in Rust with a static str value? Here is a minimal example:

struct SomeStruct {
    a: String,
}

fn main() {
    let s = SomeStruct {
        a: "Test".to_string(),
    };
    match s {
        SomeStruct { a: "Test" } => {
            println!("Match");
        }
    }
}

This won't compile because the static str reference can't be matched against the String member. Can it be made to work without destructuring a and then adding a nested if statement in the match?

like image 247
David Roe Avatar asked Mar 14 '15 12:03

David Roe


2 Answers

It is not currently possible to do this in a single pattern, though at some time it is likely to become possible. For now, it’s probably easiest to replace the pattern with a pattern and match guard, like this:

match s {
    SomeStruct { ref a } if a == "Test" => {
        println!("Match");
    }
}
like image 163
Chris Morgan Avatar answered Oct 18 '22 20:10

Chris Morgan


Thinking out of the box a bit, you can create a parallel type that has &str instead of String and add a method to convert between them:

struct SomeStruct {
    a: String,
}

impl SomeStruct {
    fn as_ref(&self) -> SomeStructRef {
        SomeStructRef { a: &self.a }
    }
}

struct SomeStructRef<'a> {
    a: &'a str,
}

fn main() {
    let s = SomeStruct {
        a: "Test".to_string(),
    };
    match s.as_ref() {
        SomeStructRef { a: "Test" } => {
            println!("Match");
        }
        _ => panic!(),
    }
}

You can then also create a constant for the value you'd like to match against:

#[derive(PartialEq, Eq)]
struct SomeStructRef<'a> {
    a: &'a str,
}

const TEST_STRUCT: SomeStructRef = SomeStructRef { a: "Test" };

fn main() {
    let s = SomeStruct {
        a: "Test".to_string(),
    };
    match s.as_ref() {
        TEST_STRUCT => {
            println!("Match");
        }
        _ => panic!(),
    }
}

There's nothing specific to structs here, the same concept works for enums:

enum SomeEnum {
    One(String),
    Two(String),
}

impl SomeEnum {
    fn as_ref(&self) -> SomeEnumRef {
        match self {
            SomeEnum::One(v) => SomeEnumRef::One(v),
            SomeEnum::Two(v) => SomeEnumRef::Two(v),
        }
    }
}

enum SomeEnumRef<'a> {
    One(&'a str),
    Two(&'a str),
}

fn main() {
    let s = SomeEnum::Two("Test".to_string());
    match s.as_ref() {
        SomeEnumRef::Two("Test") => {
            println!("Match");
        }
        _ => panic!(),
    }
}
like image 24
Shepmaster Avatar answered Oct 18 '22 21:10

Shepmaster