This is a usefull pattern on Rust match when you want to match slices of a vector.

Imagine this problem: We want to implement a function which takes an vector containing the names of people that like an item. It must return the display text as shown in the examples:

[]                                -->  "no one likes this"
["Peter"]                         -->  "Peter likes this"
["Jacob", "Alex"]                 -->  "Jacob and Alex like this"
["Max", "John", "Mark"]           -->  "Max, John and Mark like this"
["Alex", "Jacob", "Mark", "Max"]  -->  "Alex, Jacob and 2 others like this"
For 4 or more names, the number in 'and 2 others' simply increases.

We can solve this with:

fn likes(names: &[&str]) -> String {
  match names {
    [] => format!("no one likes this"),
    [a] => format!("{} likes this", a),
    [a, b] => format!("{} and {} like this", a, b),
    [a, b, c] => format!("{}, {} and {} like this", a, b, c),
    [a, b, rest @ ..] => format!("{}, {} and {} others like this", a, b, rest.len()),
  }
}

Where rest @ .. will catch all the rest of the vector items.


Another examples:

Fixed size
let arr = [1, 2, 3];
match arr {
  [1, _, _] => "starts with one",
  [a, b, c] => "starts with something else",
};

Dynamic size
let v = vec![1, 2, 3];
match v[..] {
  [a, b] => { /* this arm will not apply because the length doesn't match */ }
  [a, b, c] => { /* this arm will apply */ }
  _ => { /* this wildcard is required, since the length is not known statically */ }
};

fn foo(words: &[&str]) {
  match words {
    [] => println!("empty slice!"),
    [one] => println!("one element: {:?}", one),
    [one, two] => println!("two elements: {:?} {:?}", one, two),
    _ => println!("I'm not sure how many elements!"),
  }
}

fn foo(words: &[&str]) {
  match words {
    ["Hello", "World", "!", ..] => println!("Hello World!"),
    ["Foo", "Bar", ..] => println!("Baz"),
    rest => println!("{:?}", rest),
  }
}

fn foo(words: &[&str]) {
  match words {
    // Ignore everything but the last element, which must be "!".
    [.., "!"] => println!("!!!"),
 
    // `start` is a slice of everything except the last element, which must be "z".
    [start @ .., "z"] => println!("starts with: {:?}", start),
 
    // `end` is a slice of everything but the first element, which must be "a".
    ["a", end @ ..] => println!("ends with: {:?}", end),
 
    rest => println!("{:?}", rest),
  }
}

refs: