279

I'm trying to figure out how to match a String in Rust.

I initially tried matching like this, but I figured out Rust cannot implicitly cast from std::string::String to &str.

fn main() {
    let stringthing = String::from("c");
    match stringthing {
        "a" => println!("0"),
        "b" => println!("1"),
        "c" => println!("2"),
    }
}

This has the error:

error[E0308]: mismatched types
 --> src/main.rs:4:9
  |
4 |         "a" => println!("0"),
  |         ^^^ expected struct `std::string::String`, found reference
  |
  = note: expected type `std::string::String`
             found type `&'static str`

I then tried to construct new String objects, as I could not find a function to cast a String to a &str.

fn main() {
    let stringthing = String::from("c");
    match stringthing {
        String::from("a") => println!("0"),
        String::from("b") => println!("1"),
        String::from("c") => println!("2"),
    }
}

This gave me the following error 3 times:

error[E0164]: `String::from` does not name a tuple variant or a tuple struct
 --> src/main.rs:4:9
  |
4 |         String::from("a") => return 0,
  |         ^^^^^^^^^^^^^^^^^ not a tuple variant or struct

How to actually match Strings in Rust?

vallentin
  • 19,107
  • 6
  • 43
  • 68
Jeroen
  • 11,661
  • 11
  • 46
  • 92
  • 4
    `stringthing.as_str()` is probably the most straightforward of all the answers; I don't like `as_ref` because it's unnecessarily general, which can lead to bugs, and not as explicit, it isn't completely clear that `as_ref()` is going to be a `&str`, `as_str` is simple and clear. – Zorf Jan 10 '20 at 21:00
  • @Zorf You are right. The answer was accepted when `as_str` did not exist yet. I changed the accepted answer but thank all people who answered this question! – Jeroen Jan 10 '20 at 21:04

6 Answers6

219

as_slice is deprecated, you should now use the trait std::convert::AsRef instead:

match stringthing.as_ref() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

Note that you also have to explicitly handle the catch-all case.

Shepmaster
  • 274,917
  • 47
  • 731
  • 969
Tijs Maas
  • 2,333
  • 2
  • 14
  • 7
  • 3
    using rust 1.4.0 one can use the `trim()` function. Just using `as_ref()` doesn't match the string. – futtetennista Dec 01 '15 at 20:17
  • 1
    I think the match fails because of whitespace that `trim()` removes. This is nice for deferencing to match against user input. – Gerard Sexton Sep 20 '16 at 13:25
  • 1
    It doesn't work. It can only match _ if I get String from read_line. – Masked Man Nov 26 '16 at 10:20
  • Don't know much about how rust manages different types of strings, but [it seems to work on a basic example](https://play.rust-lang.org/?gist=d3a1379484fd4a01aa1c16e6cb32d187&version=nightly). – tforgione Jan 24 '18 at 09:40
152

You can do something like this:

match &stringthing[..] {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

There's also an as_str method as of Rust 1.7.0:

match stringthing.as_str() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}
Shepmaster
  • 274,917
  • 47
  • 731
  • 969
Anonymous Coward
  • 1,536
  • 1
  • 8
  • 2
20

You could also do

match &stringthing as &str {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

See:

Shepmaster
  • 274,917
  • 47
  • 731
  • 969
Marco Scannadinari
  • 1,566
  • 2
  • 14
  • 24
9

Editor's note: This answer pertains to an version of Rust before 1.0 and does not work in Rust 1.0

You can match on a string slice.

match stringthing.as_slice() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}
Shepmaster
  • 274,917
  • 47
  • 731
  • 969
A.B.
  • 12,107
  • 2
  • 50
  • 56
1

You can try:

fn main() {
    let stringthing = String::from("c");
    match &*stringthing {
        "a" => println!("0"),
        "b" => println!("1"),
        "c" => println!("2"),
        _ => println!("else")
    }
}
omrihhh
  • 49
  • 4
1

You can convert the String into &str by doing this:

fn main() {
let stringthing = String::from("c");
match &stringthing[..] {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
}

}