Forward UTF-8 rune cursor per ref/hare/strings/iter.ha; iterator
flattens Hare's anon-embedded utf8::decoder to explicit
offs/src/reverse fields, next() copy-in/copy-out a local decoder
and aborts on more/invalid per move()'s discipline.
The iterator flattens Hare's anonymous-embedded utf8::decoder
(ref/hare/strings/iter.ha:6-9) to explicit offs/src/reverse
fields because ww has no anon-embed syntax. reverse is retained
on the struct so riter populates it once utf8.prev (reverse DFA)
and strings.prev land.
next() copies the iterator's offs/src into a local utf8.decoder,
delegates to utf8.next, then writes offs back; copy-in/copy-out
is the cost of the flattened layout. more/invalid arms abort with
"strings.next: invalid UTF-8", mirroring Hare's move()
(ref/hare/strings/iter.ha:51-58) which aborts unconditionally
on those arms.
Deferred surface (no in-tree caller; follow-up tasks): prev, riter,
iterstr, slice, position, move. prev specifically needs utf8.prev
(reverse DFA), which isn't on the lib/encoding/utf8 surface yet.
lib/strings/strings.ww moves off test/wcc/900_stdlib.c's
standalone-compile list per the existing bufio/fmt/os precedent:
the iterator's (rune | utf8.done) return type and the local
utf8.decoder reference need cross-module type resolution, which
the standalone w6c path doesn't do. Runtime coverage stays at
966_strings_run, which now exercises 21 signalled cases (was 15).
The iterator's Hare-faithful `reverse: bool` field surfaced #33
(cstage cgen narrow-sret-field copy mis-width) during this port's
pre-flight; that fix landed at 0d96196 ahead of this commit.
Future bisecters tracking a narrow-field-related regression in
lib/strings or sret-aware stdlib growth should consult #33 + this
commit's bracket. The 4-arm match on utf8.next return surfaced
#31 (wwstage fnretlookupmod) earlier in the same chain (b787641).
Tests:
- 6 new @test fns in stringstest.ww (signalled 16-21): empty,
ASCII, 2-byte (café), 3-byte (こんにちは), 4-byte (🦀rust),
mixed-width ("Hello, 世界! 🌍"). Each verifies forward
iteration, done@EOI, and repeated next-after-done stays done
(iter_empty). Multibyte literal limitation handled via
`0xE9u32: rune` cast per existing pattern at stringstest.ww:82.
104/104 ok. 995_self_rebuild stays green (ww2==ww3==ww4 byte-id).