Introduction
Rust uses String for owned, growable text and &str for a borrowed view of text. A string slice can view an entire string or a selected byte range without copying its characters.
You will pass owned text to a function that borrows &str, create a borrowed command keyword, and intentionally ask the compiler to index UTF-8 text in an unsupported way before repairing it with a valid boundary-aware slice.
Borrow Owned and Literal Text as &str
In this step, you will pass two different text sources to one function that accepts a borrowed string slice.
Enter the prepared project and open its source:
cd /home/labex/project/string-slices
nano src/main.rs
The type String owns growable text. The type &str, pronounced “string slice,” is a borrowed view into valid UTF-8 text. A string literal such as "preview" already has a borrowed string-slice type because the program stores its text for the entire run.
The function show_text(label: &str) can view either kind of text. Replace only /* Step 1: borrow command */ with &command:
show_text(&command);
Rust automatically treats the borrowed &String as the &str view the function requests. This conversion does not copy or move the characters.
Save with Ctrl+O, press Enter, and exit with Ctrl+X. Run the program:
cargo run --quiet
The output should be:
Text: serve reports
Text: preview
Keyword: <>
Status: ✅ ready
Both calls reach the same &str parameter. The empty keyword is a prepared placeholder for the next step.
Borrow a Substring Without Copying
In this step, you will make keyword view only the serve prefix inside command.
Open the source:
nano src/main.rs
The slice form &text[start..end] borrows a range. The start is included and the end is excluded. Rust string ranges count bytes, and the ASCII letters in serve each occupy one byte, so the range begins at byte 0 and ends before byte 5.
Replace only the empty literal "" on the Step 2 line with &command[0..5]:
let keyword = &command[0..5]; // Step 2: replace the empty slice.
The resulting &str points into command; it does not allocate or copy a second string. Because command remains in scope, the borrowed view stays valid while keyword is used.
Save and exit, then run:
cargo run --quiet
The final line should now be:
Keyword: <serve>
The owned command still contains the complete serve reports text, while keyword is only a borrowed window into its first five bytes.
Respect UTF-8 Character Boundaries
In this step, you will intentionally try integer indexing, read the compiler's explanation, and replace it with a valid UTF-8 slice.
UTF-8 characters do not all occupy one byte. In "✅ ready", the check-mark symbol uses three bytes. Therefore byte zero is not automatically “the first character,” and Rust does not allow status[0] on a String.
Open the file and remove only the leading // from the Step 3 print line:
nano src/main.rs
Save and exit, then run the check. Failure is expected:
cargo check
Find the stable message:
error[E0277]: the type `str` cannot be indexed by `{integer}`
The diagnostic protects you from pretending every character has a one-byte position. Open the file again and replace that failing print line with these two short lines:
let symbol = &status[0..3];
println!("Status symbol: {symbol}");
The range 0..3 ends exactly after the three-byte symbol. This works because the prepared text and its byte boundary are known in advance; it is not a general recipe for finding the first human-visible character in arbitrary text. A range that cuts through the middle of a UTF-8 character would panic at runtime, so string ranges must come from known valid boundaries.
Save and exit, then check and run:
cargo check
cargo run --quiet
The complete output should be:
Text: serve reports
Text: preview
Keyword: <serve>
Status: ✅ ready
Status symbol: ✅
The successful output proves that the final slice selects one complete UTF-8 character without copying the original String.
Summary
You connected owned String values and borrowed &str views, selected a substring without allocation, and learned why UTF-8 text cannot be treated as a byte-indexed character array. Safe string ranges must begin and end on valid UTF-8 boundaries.


