Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

std.unicode

Normalization and a deliberately small classification surface, pinned to Unicode 17.0.0 independently of the host Rust compiler. version() returns the string "17.0.0".

FunctionResult
nfd(text: &str, max_scalars: NonNegative[i64])Canonical decomposition
nfc(text: &str, max_scalars: NonNegative[i64])Canonical decomposition and composition
nfkd(text: &str, max_scalars: NonNegative[i64])Compatibility decomposition
nfkc(text: &str, max_scalars: NonNegative[i64])Compatibility decomposition and canonical composition
combining_class(scalar: &str)Option[u32]: canonical combining class of exactly one scalar
is_mark(scalar: &str)Option[bool]: General_Category is Mark for exactly one scalar
import std.unicode
from std.text import TextError

def main() -> Result[(), AllocError | IoError | TextError]:
    decomposed = std.unicode.nfd("café", 64)?
    print(len("café"), len(decomposed), std.unicode.nfc(&decomposed, 64)? == "café")?
    accent = decomposed[4]
    print(std.unicode.is_mark(&accent), std.unicode.combining_class(&accent))?
    print(std.unicode.nfkc("file ①", 64)?)?
    Ok(())
4 5 True
Option[bool].Some(True) Option[u32].Some(230)
file 1

Normalization returns Result[str, std.text.TextError]. It borrows input and returns independent text. The explicit scalar limit bounds the input, fully decomposed intermediate, and result. Exceeding any gives LimitExceeded. The limit is NonNegative[i64], and a limit above i64.MAX // 4 traps. An empty string fits a zero limit. Output UTF-8 is consequently at most four times the limit. Normalization’s explicit arithmetic opt-outs rely on that validated ceiling, successfully appended scalar counts, and positive insertion-sort indices. They do not bypass scalar limits or allocation failures, and normalization adds no arithmetic error variants to TextError. The limit counts Unicode scalars, not bytes or grapheme clusters, and canonical composition does not let an oversized decomposition bypass it.

Classification allocates nothing and returns Nothing for zero or multiple scalars. Mark and nonzero combining class are distinct properties. This module does not offer locale collation, case folding, or general categories beyond Mark. Grapheme, word and sentence segmentation and display width are in the official unicode_text package, described with text segmentation and width. Existing string casing and ASCII classification remain the text builtins. Compatibility normalization can erase meaningful presentation distinctions; callers choose it explicitly. No implicit normalization occurs in equality, hashing, paths, decoding, or text builders.

Stable canonical ordering and blocked composition follow UAX #15, including Hangul and composition exclusions. Checked Plenty performs the algorithms; allocation-free scalar lookups reuse bundled unicode-normalization 0.1.25 tables and primitives. Canonical ordering uses stable insertion: O(n²) worst-case time for adversarial descending combining runs, O(n) otherwise, where n is decomposed scalar count. Storage is O(n), with two scalar lists and bounded UTF-8 construction; allocation failure is recoverable. Choose a suitably small limit for untrusted input. No hidden global state or thread affinity is introduced; ordinary ownership and worker-effect checking still apply.

The complete Unicode 17 NormalizationTest.txt fixture checks all twenty normalization equalities for each row through one compiled Plenty harness. Unicode upgrades are deliberate source changes: replace the pinned upstream sources, update the version function, fixture and licenses together, and rerun the corpus, allocation tests, tutorial tests and packaging tests. Do not derive table versions from the host toolchain. Vendoring preserves the dependency-free runtime build and avoids the upstream iterator’s infallible scratch allocation. Provenance and exact update steps are recorded beside the vendored sources.

The native tables add no external libraries or build-time network access and ship inside both runtime archives. Supported target: x86_64 Linux GNU. See the lesson and std.text for bounded output construction and error variants.

Acknowledgements