Skip to content
Select theme

How to reverse a string

Short answer: String and str have no reverse() method — write s.chars().rev().collect::<String>() to reverse by characters. The method is missing because a String is a buffer of UTF-8 bytes, and reversing those bytes produces text that isn’t valid UTF-8, which a String may not hold. Vec has reverse() because its elements are fixed-size values, where “backwards” is unambiguous.

From a fresh project — cargo new reverse-demo, then replace src/main.rs with each block below and run it with cargo run. The project name only shows up in cargo’s own output; nothing else on this page depends on it.

hello -> olleh
café -> éfac
😀hi -> ih😀

chars() walks the characters one at a time — the iteration article covers the walk — and the Chars iterator is double-ended, so .rev() walks it from the end instead. String implements FromIterator<char>, which is what turns the characters back into text; the iteration article meets the same collector from the other direction. One pass over the input, one String out.

Vec has the method. Every element is the same size, so reversing is a matter of swapping fixed-size slots:

[3, 2, 1]

A String is a Vec<u8> whose contents have to stay valid UTF-8, and a character is one to four bytes — the fact that rules out s[0], as the previous article shows. Reverse the bytes of “café” and the é — 0xC3 0xA9 — comes out as 0xA9 0xC3, a continuation byte leading, which is not a character and not valid UTF-8. A method that did this could not return a String:

[169, 195, 102, 97, 99]
invalid utf-8 sequence of 1 bytes from index 0

from_utf8 checks the bytes as it converts and hands back the error instead of the corrupted text; the conversion itself gets its own article later in this chapter. Asking for the missing method directly gets the compiler’s version of the same answer:

error[E0599]: no method named `reverse` found for struct `String` in the current scope
--> src/main.rs:3:25
|
3 | let reversed = text.reverse();
| ^^^^^^^
|
help: there is a method `reserve` with a similar name, but with different arguments
--> /rustc/b940084d7eb6a299eb4bfeb8e34901bc051e7ac4/library/alloc/src/string.rs:1235:4
For more information about this error, try `rustc --explain E0599`.

The help line offers reserve, which is about capacity, not order — the compiler matched the name, not the meaning. Nothing in the standard library reverses text for you, so the level to reverse at is the reader’s choice.

Reversing by char splits some visible letters in two. An “e” followed by a combining acute accent prints as one letter and is two chars — the iteration article makes the same point about counting. Reversed, the accent comes first:

"e\u{301}" is 2 chars and 3 bytes
"\u{301}e"
equal: false

The escapes make the difference plain: in the reversed string the accent comes before the letter. The two are different strings — == says so on the last line — and a search for the original won’t match the reversed text. When “reversed” has to mean “one visible letter stays one letter”, the unit is the grapheme cluster, and the standard library doesn’t cut text that way: the unicode-segmentation crate does, with graphemes(true) walking clusters the way chars() walks scalars. For the string above it counts one cluster, and reversing by clusters returns the same string.

Lovelace Ada

split_whitespace() hands out the pieces — the splitting article covers it — its iterator is double-ended too, and join puts the spaces back. Reversing words leaves the characters inside each word in order, which is often what “reverse the sentence” means in practice.