String methods¶
Level: reference · for working programmers
One line: One page per method on String — all 42 that stable Rust 1.98 exposes — each with the signature, the behaviour at the edges, and a runnable program whose output CI checks.
String owns its text and can grow it. That is the whole difference from str, and it is why this list is short: everything about reading text is over there, reached automatically because String dereferences to str. What is here is the part that needs ownership — building, growing, removing, and handing the allocation somewhere else.
So if you are looking for split, trim, find, replace or parse, they are on the str side and they work on a String unchanged.
Same page shape as the str reference: summary, signature, stability, prose, then a complete program and its verified output.
The three numbers¶
Every method below moves one of three numbers, and confusing them is most of the difficulty:
| what it is | changed by | worked example | |
|---|---|---|---|
len() |
bytes written | push, push_str, truncate, clear, pop, … |
len |
capacity() |
bytes the buffer can hold | reserve, shrink_to_fit, and growth |
capacity |
chars().count() |
Unicode scalars | nothing directly — it is derived by walking | str::chars |
The last column is a page whose program prints that number moving, compiled and run by CI, so you can watch the row happen rather than take it on trust. The len page covers all three in six lines of output — len 6 chars 5, then len 6 capacity 64. For the bytes-per-character half on its own, push pushes 'a', 'é' and '👋' and prints the length after each: 1, 3, 7. For the growth curve, capacity watches the buffer go 0 → 8 → 16 → 32 under three push_str calls.
len is part of the value; capacity is not. Two strings with the same text and different capacities are equal, hash the same, and print the same — so never assert on a capacity in a test.
Byte offsets panic in two ways¶
insert, remove, truncate, drain, replace_range, split_off and extend_from_within all take byte offsets, and all panic on the same two conditions: out of range, or inside a character. is_char_boundary is the test and floor_char_boundary is the repair — all seven of those examples call the test, and truncate's does the repair: a byte budget of 2 lands inside the é of "héllo wörld", and flooring it first truncates to "h" instead of panicking.
Making one¶
| method | what it does |
|---|---|
new |
Empty, and allocates nothing until the first push |
with_capacity |
Empty, with the buffer bought up front |
from_utf8 |
Validate a Vec<u8> — no copy, and the Vec comes back on failure |
from_utf8_lossy |
Bad bytes become �; returns a Cow, so clean input is free |
from_utf16 |
Decode UTF-16 code units; fails on an unpaired surrogate |
from_utf16_lossy |
The same, replacing instead of failing |
from_utf16le |
Decode little-endian UTF-16 bytes |
from_utf16le_lossy |
The same, replacing instead of failing |
from_utf16be |
Decode big-endian UTF-16 bytes |
from_utf16be_lossy |
The same, replacing instead of failing |
Growing it¶
len is what you wrote; capacity is what you paid for.
| method | what it does |
|---|---|
push |
One char — which is 1–4 bytes, so len grows by more than one |
push_str |
Text on the end — the workhorse |
insert |
One char at a byte offset, shifting the rest — O(n) |
insert_str |
Text at a byte offset — prepending always costs a copy |
extend_from_within |
Append a copy of one of its own ranges, no temporary |
capacity |
Bytes the buffer holds — not part of the value |
reserve |
Room for n more bytes — a headroom, not a total |
reserve_exact |
The same without the round-up |
try_reserve |
reserve that returns Result instead of aborting |
try_reserve_exact |
Exact, and reporting |
shrink_to_fit |
Give the spare capacity back — usually by copying |
shrink_to |
Shrink toward a floor you name, for a reused buffer |
Taking things out¶
| method | what it does |
|---|---|
pop |
The last char — O(1), returns Option, cannot panic |
remove |
The char at a byte offset — O(n), and it panics |
truncate |
Drop everything past an offset — panics off a boundary |
clear |
Empty it and keep the buffer — the reusable-buffer idiom |
drain |
Remove a range and read what went |
retain |
Keep what a predicate approves — one linear in-place pass |
replace_range |
Swap a range for different text, in place |
split_off |
Cut at an offset and get the tail as an owned String |
Looking at it, and giving it away¶
The first four borrow; the rest consume.
| method | what it does |
|---|---|
len |
The byte count |
is_empty |
len() == 0 — capacity is irrelevant |
as_str |
The whole thing as &str — usually supplied by deref coercion |
as_mut_str |
As &mut str — mutable, but length-preserving |
as_bytes |
The UTF-8 bytes, borrowed |
into_bytes |
The Vec<u8>, owned — no copy, no UTF-8 promise |
into_boxed_str |
A Box<str> — shrinks, and drops the capacity field |
into_raw_parts |
Pointer, length, capacity — and the destructor stops running |
leak |
A &'static mut str that is never freed |
unsafe — the checks removed¶
| method | what it does |
|---|---|
from_utf8_unchecked |
Take a Vec<u8> with no validation |
as_mut_vec |
The underlying Vec<u8>, resizable — you owe valid UTF-8 back |
from_raw_parts |
Rebuild from pointer, length and capacity — all three exact |
Where to go next¶
strmethods — the borrowed half, 83 more pages, and where all the reading lives- The strings arc — the lessons these pages are a reference for
Stringin the standard library ↗ — the official documentation these pages explain
Po polsku¶
To jest spis — po jednej stronie na każdą z 42 metod, które String udostępnia w stabilnym Ruscie 1.98. Podział między String a str warto sobie ułożyć raz i mieć go z głowy: String posiada tekst i potrafi go powiększyć, więc tutaj trafiło wszystko, co wymaga własności — budowanie, dopisywanie, usuwanie, oddanie bufora dalej. Całe czytanie (split, trim, find, replace, parse) mieszka po stronie str i działa na String bez żadnej konwersji, bo String dereferencjuje się do str — dlatego ta lista jest krótka, a tamta ma ponad osiemdziesiąt pozycji.
Trzy liczby, których mylenie jest największym źródłem kłopotów, mają dla polskiego czytelnika dodatkowy haczyk: len() zwraca bajty, a nie znaki, i nasze ogonki pokazują to natychmiast — "żółw" ma cztery znaki, ale siedem bajtów, bo ż, ó i ł zajmują w UTF-8 po dwa. Liczbę znaków daje dopiero chars().count(), i to przechodząc po całym łańcuchu znaków, więc nie jest to odczyt pola, tylko pętla. Trzecia liczba, capacity(), mówi wyłącznie, ile bufor może pomieścić, i nie jest częścią wartości: dwa łańcuchy o tym samym tekście i różnej pojemności są równe i tak samo się haszują — nigdy nie pisz testu, który sprawdza capacity().
Z tej samej różnicy bierze się druga pułapka. Metody przyjmujące przesunięcie w bajtach — insert, remove, truncate, drain, replace_range, split_off, extend_from_within — panikują na dwa sposoby: gdy przesunięcie wychodzi poza zakres oraz gdy wypada w środku znaku. Dla let mut s = String::from("żółw") wywołanie s.truncate(3) to właśnie ten drugi przypadek, bo trójka trafia między dwa bajty ó. Testem jest is_char_boundary, naprawą floor_char_boundary, które cofa przesunięcie do najbliższej poprawnej granicy — strona truncate pokazuje to na "héllo wörld" przy budżecie dwóch bajtów.
Szukaj po polsku: długość łańcucha w bajtach a w znakach · polskie znaki w UTF-8 · granica znaku w Ruscie · rust String len vs chars count · rust byte index is not a char boundary