diff --git a/lib/encoding/utf8/utf8.ww b/lib/encoding/utf8/utf8.ww index 05adc89c..60e5c97f 100644 --- a/lib/encoding/utf8/utf8.ww +++ b/lib/encoding/utf8/utf8.ww @@ -29,6 +29,12 @@ export type more = void; // ref/hare/encoding/utf8/types.ha:9 — invalid UTF-8 sequence. export type invalid = !void; +// ref/hare/encoding/utf8/types.ha:12 — fixed message; `invalid` carries +// no payload, so the rendering is constant. +export fn strerror(err: invalid) str = { + return "Invalid UTF-8"; +}; + // `done` is not a built-in singleton in ww (Hare ships it as part of // the type system). Plain `void` (not `!void`): end-of-input is a // continuation signal, not an error. lib/io spells its EOF the same diff --git a/lib/encoding/utf8/utf8test.ww b/lib/encoding/utf8/utf8test.ww index 78cbefca..62f6b711 100644 --- a/lib/encoding/utf8/utf8test.ww +++ b/lib/encoding/utf8/utf8test.ww @@ -12,6 +12,16 @@ import os; let signalled: i32 = 0; fn fail() void = { os.exit(signalled + 10); }; +fn streq(a: str, b: str) bool = { + if (a.len != b.len) { return false; }; + let i: i32 = 0; + for (i < a.len) { + if (a[i] != b[i]) { return false; }; + i += 1; + }; + return true; +}; + // ---- runesz: byte length per range ------------------------------------ // ref/hare/encoding/utf8/rune.ha:5. Boundaries: 0x7F → 1, 0x80 → 2, // 0x7FF → 2, 0x800 → 3, 0xFFFF → 3, 0x10000 → 4, 0x10FFFF → 4. @@ -575,6 +585,15 @@ fn fail() void = { os.exit(signalled + 10); }; if (utf8.remaining(&d1).len != 0) { fail(); }; }; +// ---- strerror: constant rendering ------------------------------------- +// ref/hare/encoding/utf8/types.ha:12. `invalid` is payload-free; the +// renderer collapses to a single fixture row. + +@test fn strerror_cases() void = { + let e: utf8.invalid; + if (!streq(utf8.strerror(e), "Invalid UTF-8")) { fail(); }; +}; + // ---- round-trip: encode → decode → equal rune -------------------------- @test fn roundtrip() void = { @@ -636,5 +655,6 @@ export fn main() i32 = { signalled = 33; prev_max_in_range(); signalled = 34; prev_min_out_of_range(); signalled = 35; remaining_slice_position(); + signalled = 36; strerror_cases(); return 0; }; diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index d052f69a..7004e390 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -1429,6 +1429,12 @@ export type more = void; // ref/hare/encoding/utf8/types.ha:9 — invalid UTF-8 sequence. export type invalid = !void; +// ref/hare/encoding/utf8/types.ha:12 — fixed message; `invalid` carries +// no payload, so the rendering is constant. +export fn strerror(err: invalid) str = { + return "Invalid UTF-8"; +}; + // `done` is not a built-in singleton in ww (Hare ships it as part of // the type system). Plain `void` (not `!void`): end-of-input is a // continuation signal, not an error. lib/io spells its EOF the same diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index ea00e91e..881f01a8 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -1429,6 +1429,12 @@ export type more = void; // ref/hare/encoding/utf8/types.ha:9 — invalid UTF-8 sequence. export type invalid = !void; +// ref/hare/encoding/utf8/types.ha:12 — fixed message; `invalid` carries +// no payload, so the rendering is constant. +export fn strerror(err: invalid) str = { + return "Invalid UTF-8"; +}; + // `done` is not a built-in singleton in ww (Hare ships it as part of // the type system). Plain `void` (not `!void`): end-of-input is a // continuation signal, not an error. lib/io spells its EOF the same diff --git a/selfhost/test/smoke.combined.ww b/selfhost/test/smoke.combined.ww index e3eba485..994d60c3 100644 --- a/selfhost/test/smoke.combined.ww +++ b/selfhost/test/smoke.combined.ww @@ -1320,6 +1320,12 @@ export type more = void; // ref/hare/encoding/utf8/types.ha:9 — invalid UTF-8 sequence. export type invalid = !void; +// ref/hare/encoding/utf8/types.ha:12 — fixed message; `invalid` carries +// no payload, so the rendering is constant. +export fn strerror(err: invalid) str = { + return "Invalid UTF-8"; +}; + // `done` is not a built-in singleton in ww (Hare ships it as part of // the type system). Plain `void` (not `!void`): end-of-input is a // continuation signal, not an error. lib/io spells its EOF the same