Shiklo Tools
PDF40
Image20
Calculators & Converters25
Text & Writing13
Developer26
Video14
Audio14
Document14
Data & Spreadsheet12
Web & SEO9
OCR & Scanning5
Archive & File12
Security & Privacy23
Health & Medical29
QR & Barcode5

Rust Slices

A slice is a view of part of a collection, like a window onto some of the items. It does not copy anything; it simply points at a stretch of a string, an array or a vector. You have already used one kind of slice without knowing it: &str is a string slice.

Slicing a string

You make a slice with a range in square brackets. &text[0..4] means the bytes from position 0 up to, but not including, position 4:

fn main() {
    let text = String::from("Hello Rust");
    let hello = &text[0..5];
    let rust = &text[6..];
    println!("[{}] [{}]", hello, rust);
}
Output
[Hello] [Rust]

Leaving out the start, as in [..5], means "from the beginning", and leaving out the end, as in [6..], means "to the end". The positions count bytes. For plain English text that is the same as letters; for other alphabets it is safer to use methods like chars or split, because slicing in the middle of a multi-byte character stops the program.

Why &str makes great parameters

When a function only needs to read text, the kindest type to accept is &str. It works with string literals, with a borrowed String, and with slices, all at once:

fn first_word(text: &str) -> &str {
    match text.find(' ') {
        Some(space) => &text[..space],
        None => text,
    }
}

fn main() {
    let owned = String::from("good morning everyone");
    println!("{}", first_word(&owned));
    println!("{}", first_word("hello"));
    println!("{}", first_word(&owned[5..]));
}
Output
good
hello
morning

The returned &str is a window into the original text, so no new text is created. Rust also makes sure the original cannot be changed or dropped while the window is still in use, which is borrowing at work again.

Slices of arrays and vectors

The same idea works for lists of numbers. A slice of numbers has the type &[i32], and functions that take one can work with arrays and vectors alike:

fn total(numbers: &[i32]) -> i32 {
    let mut sum = 0;
    for n in numbers {
        sum += n;
    }
    sum
}

fn main() {
    let week = [3, 5, 2, 8, 6, 9, 4];
    println!("Whole week: {}", total(&week));
    println!("Weekdays: {}", total(&week[..5]));
    println!("Weekend: {}", total(&week[5..]));
}
Output
Whole week: 37
Weekdays: 24
Weekend: 13

If a range goes past the end, for example &week[5..10] on a list of 7 items, the program stops with a message that says so. Rust never quietly reads memory that does not belong to the list.

Practice exercises

  1. Print the first three letters and the last three letters of the word "programming" using slices.
  2. Write fn last_word(text: &str) -> &str using rfind(' ').
  3. Write a function that returns the largest number in a &[i32] slice.