The string crates, and what std makes you do without them¶
Level: reference · the reading list
One line: Fifteen crates cover the text jobs std leaves out — graphemes, normalization, legacy encodings, locales, bytes that are not UTF-8, short strings off the heap — and each one sits beside the lesson here that says what std gives you instead.
Nothing on this page ran. Every example in this library is bare rustc with no crates, so a crate can be described here and never demonstrated. What a row says a crate is for paraphrases the crate's own published description; the Latest and Released columns were read from the crates.io API on 2026-09-10 and are a snapshot. The std instead column links lessons whose claims are checked.
Text as a reader sees it¶
std counts and compares scalar values and bytes. It has no notion of what a reader calls one character, of which two spellings are the same word, or of what the reader's language says about either.
| Crate | What it is for | Latest | Released | std instead |
|---|---|---|---|---|
unicode-segmentation ↗ |
Grapheme-cluster, word and sentence boundaries, by Unicode's UAX #29 | 1.13.3 | 2026-06-01 | chars() yields scalar values, not what a reader counts — Four lengths, and which one the other system means |
unicode-normalization ↗ |
The four normalization forms — NFC, NFD, NFKC, NFKD — by UAX #15 | 0.1.25 | 2025-10-30 | Nothing: == and sort() compare the bytes you were given — Comparing and sorting text |
icu ↗ |
The meta-crate of the ICU4X project: its internationalization components, re-exported, with the CLDR locale data they are driven by | 2.3.1 | 2026-08-20 | Nothing: str has no locale, so case mapping and ordering are the same on every machine — see the row above |
Bytes that are not UTF-8¶
A String is UTF-8 by type. These are for text that arrived some other way, and for the byte order of the numbers around it.
| Crate | What it is for | Latest | Released | std instead |
|---|---|---|---|---|
encoding_rs ↗ |
The WHATWG Encoding Standard, as implemented for Firefox's Gecko engine — the legacy encodings a web page or an old file may be in | 0.8.41 | 2026-09-09 | UTF-8 and UTF-16, and nothing else — String::from_utf16 |
bstr ↗ |
A string type for bytes that are mostly text but not promised to be UTF-8 | 1.13.1 | 2026-08-10 | &[u8], and OsStr for what the operating system hands you — Six kinds of string |
widestring ↗ |
Owned wide strings, u16 and u32, for Windows APIs and other FFI |
1.2.1 | 2025-10-09 | Conversion only — no UTF-16 string type — str::encode_utf16 |
utf16string ↗ |
String types that store UTF-16 directly | 0.2.0 | 2020-10-10 | as for widestring |
byteorder ↗ |
Reading and writing numbers big- or little-endian | 1.5.0 | 2023-10-06 | to_be_bytes / from_le_bytes and friends, on the integer types themselves — Meet the byte |
Short strings, off the heap¶
A non-empty String always owns a heap buffer — three words on the stack, the text behind a pointer. Most of these keep short text inside the handle instead, which is the small-string optimization; the last makes a clone cheaper than a copy.
| Crate | What it is for | Latest | Released | std instead |
|---|---|---|---|---|
compact_str ↗ |
A string that stays on the stack while it is short enough, and moves to the heap when it is not | 0.10.0 | 2026-07-13 | Always the heap — The anatomy of a String |
smartstring ↗ |
Short strings stored inline in the handle | 1.0.1 | 2022-03-24 | as above |
smallstr ↗ |
A String-like type built on smallvec's inline buffer |
0.3.1 | 2025-08-13 | as above |
tinystr ↗ |
ASCII only, with a fixed maximum length, never on the heap | 0.8.4 | 2026-08-13 | as above |
arraystring ↗ |
A fixed-capacity string on the stack | 0.3.0 | 2019-01-21 | as above |
flexstr ↗ |
An immutable, clone-efficient replacement for String, in local and thread-shared forms for str, bytes, CStr, OsStr and Path |
0.11.7 | 2026-02-28 | Rc<str> / Arc<str> — The third owned form |
Allocation you did not ask for¶
| Crate | What it is for | Latest | Released | std instead |
|---|---|---|---|---|
cow-utils ↗ |
Copy-on-write versions of the str methods that return a new String even when nothing needed changing — plus its own stand-in for Pattern, which std still keeps unstable |
0.1.3 | 2023-09-26 | replace hands back a new String every time; Cow is the tool — Replacing part of a string · Cow: borrow until somebody writes |
Reading the columns¶
- Released is the newest version's publish date. crates.io also reports an
updated_at, which moves for reasons that are not releases, so it is not used here. Two of these have not published since 2019 and 2020; a small crate can simply be finished, but that is worth checking before you depend on one. - Downloads are left out. crates.io counts every fetch, including each time a crate arrives as someone else's dependency, so the number measures how widely a crate is pulled in — which is a different question from whether you should choose it.
stdinstead names what you have without the crate. Most programs never need a row of this table.
Where std draws the line¶
std does carry some of Unicode's tables — the ones behind a char's own properties and its case mappings, such as is_alphabetic, is_whitespace and to_lowercase. It stops there: normalization, segmentation and locale data are left to crates. The hard strings ↗, in the sibling encodings library, runs the same sixteen look-alike pairs through Rust's std and through Python's standard library, and shows where each one stops.
See also¶
- STRINGS.md — every string lesson, in the order the questions come up
- Strings: links, books and videos — the reading list this page sits beside
- When
Stringis too slow — the stub that decides when the third table is worth reaching for - Scratch programs with a crate — how to try one of these without starting a project