v0.34.0 Phase 2 UTF-8 Iteration Review
Result: complete with no open finding (2026-09-04). UTF-8 validation and borrowed scalar iteration now consume one decode-step authority.
Closed Product
std/internal/utf8.decode_scalar owns leading-byte classes, continuation requirements, overlong rejection, surrogate rejection, maximum-scalar rejection, and exact byte width. Complete UTF-8 validation advances only through its returned width. str.chars retains the borrowed text and a single byte-boundary offset; Chars.next advances through the same step and uses the trusted package-internal character representation bridge only after decode success. str.char_count consumes Chars rather than maintaining another traversal.
Unchecked character transport now lives in std/internal/character. The public char module owns dynamic scalar validation, while the internal UTF-8 consumer can transport a scalar it has already validated. The standard profile is the sole physical locator for these primitive roles and Target requires their package-only signatures. No module-name workaround or duplicated validity check remains.
Findings Closed During Implementation
The first integration run exposed that a consuming accessor on a copy decode-step made sequential field observation depend on implicit copying. The decode-step is now a package-visible immutable data contract with readonly scalar and width fields; consumers do not need wrapper methods or hidden copy behavior.
Fixed-array test input also exposed that an explicit array-reference cast was not an applicable borrow coercion. The tests construct byte views through the existing pointer projection authority, which is the same explicit unsafe boundary used by other internal fixed-buffer code.
Evidence
- decoder tests cover one-, two-, three-, and four-byte scalars plus overlong, surrogate, and above-maximum rejection;
- the complete bundled-standard target session accepts the physical package and all primitive contracts;
- the native Unicode test executes mixed ASCII, two-byte, and four-byte iteration, exact byte and scalar counts, scalar order, end-of-iteration, and dynamic surrogate rejection;
- source audit finds no second UTF-8 leading-byte table in the standard package;
cargo test --workspace --lib --quiet, Rust formatting, documentation generation, and diff hygiene pass for the closed phase.