0

I want to check whether a particular nested field is equal to a certain String and only run the arm if it is. Something like the following:

struct Bar {
    baz: usize,
    value: Option<String>
}

struct Foo {
    bar: Bar
}

let value = Foo { bar: Bar { baz: 1, value: Some("foobar".to_string()) } };

match value {
    Foo {
        bar: Bar {
            baz,
            value: Some("foobar") // does not work since &str != String
        }
    } => println!("Matched! baz: {}", baz),
    _ => panic!("No Match")
}

Adding a match guard works but constant Strings aren't a thing so I can't guard using that, the only possibility I see is to guard against a new String like so:

struct Bar {
    value: Option<String>
}

struct Foo {
    bar: Bar
}

let value = Foo { bar: Bar { value: Some("foobar".to_string()) } };

match value {
    Foo {
        bar: Bar { baz, value },
    } if value == Some("foobar".to_string()) => println!("Matched! baz: {}", baz),
    _ => panic!("No Match"),
}

Is this my only option or is there a better way?

Note: I have seen How to match a String against string literals? but my match is nested and more complicated (the above is only an example) so I can't just match against a reference to the String.

cafce25
  • 15,907
  • 4
  • 25
  • 31
user3690467
  • 3,049
  • 6
  • 27
  • 54
  • 1
    If I understood correctly, there is a feature that is WIP in the compiler that will allow you to match the nested string with a literal `&str`. This is part of a bigger project to allow nested matching over values that are obtained by dereferencing the matched value (this would be possible in your case because `String: Deref`). This is partly possible right now, but they [the Rust lang team] are waiting to have a fully general solution before making it available. – jthulhu May 31 '23 at 09:30

1 Answers1

1

You can extract the value inside the Some, which would give you a value of type String, which you can then compare with == in an if guard:

    match value {
        Foo {
            bar: Bar {
                baz,
                value: Some(value),
            },
        } if value == "foobar" => println!("Matched! baz: {}", baz),
        _ => panic!("No Match"),
    }

Output:

Matched! baz: 1

Playground

As @drewtato pointed out in a comment below, this will move the whole value. If you want to reuse value again, you can match with Some(ref value) and the comparison will still work.

Dogbert
  • 212,659
  • 41
  • 396
  • 397