// Hare splits the io module across stream.ha + types.ha and ww does // the same (#94 fold-eFinal). The four files share `package io;` so // cross-file refs resolve via the dir-enum concat order (io.ww < // stream.ww < types.ww — `stream` lands before the reader/writer/ // closer aliases below). // // Deferrals (drew-signed): `copier`, `strerror` (the #5 list's // `handle` + `seeker` landed with the #5 arc and the memio-seeker // port). Hare's `EOF = done` stays as `io.eof` until the `done` // singleton ships (#93). package io; import errors; // ref/hare/io/types.ha:29-34. RDWR is spelled `3` rather than Hare's // `READ | WRITE` because the ww parser doesn't fold expressions in // enum value positions; the value SSoT stays the same bitfield. export type mode = enum u8 { NONE = 0, READ = 1, WRITE = 2, RDWR = 3, }; // ref/hare/io/types.ha:37-41. Hare leaves the underlying implicit; // ww requires one. i32 matches the off type that fold-e2 will plug // into the seeker signature. export type whence = enum i32 { SET = 0, CUR = 1, END = 2, }; // ref/hare/io/+linux/platform_file.ha:13. Hare's `file = int`; on // linux/x86_64 Hare's `int` is 32-bit, but ww's `int` is an 8B machine // word, so a literal `int` here would be width-wrong for a fd. i32 is // width-faithful to Hare's real fd width (USER-ruled 2026-05-31). export type file = i32; // ref/hare/io/arch+x86_64.ha:6. ABI-compatible with POSIX off_t. export type off = i64; // ref/hare/io/handle.ha:12. Hare spells it `(file | *stream)`; ww's // `stream` is already `*vtable` (the #94 collapse absorbed Hare's // `*stream` indirection), so the faithful ww payload is `(file | // stream)`, NOT a literal `*stream` which would be a double-pointer. export type handle = (file | stream); // ref/hare/io/types.ha:11 spreads `...errors::error` into the union; // ww enumerates the tags explicitly (ken's #204-block — spread of an // errors-side tagged into this union triggers a wrapper-vs-flatten // layout mismatch; #199b layout-extension is the deferred fix). The // read/write dispatchers in stream.ww return `errors.unsupported` // when the matching vtable slot is unset, so the variant lands here // directly. `errors.invalid` rides the memio-seeker port (Hare's // memio seek returns errors::invalid on out-of-bounds, // ref/hare/memio/stream.ha:134-136); appended last so existing // member tags stay put. export type error = !(errors.unsupported | underread | nomem | errors.invalid); // ref/hare/io/types.ha:46. `eof` (not Hare's `done`) per the io.ww // rationale; lifts to `done` with #93. `stream` forward-refs the // `*vtable` alias in stream.ww — the dispatcher receives the vtable // pointer directly (Hare's stream.ha:33 + types.ha:46 collapse). export type reader = fn(s: stream, buf: []u8) (size | eof | error); // ref/hare/io/types.ha:51. No `const` qualifier — ww has none, and // lib/sort/sort.ww:18 drops it the same way. export type writer = fn(s: stream, buf: []u8) (size | error); // ref/hare/io/types.ha:55. export type closer = fn(s: stream) (void | error); // ref/hare/io/types.ha:76. Hare's `fn(s: *stream, off: off, w: whence)`; // ww's `stream` is already `*vtable` (the #94 collapse), so the param is // `stream` directly, mirroring the reader/writer/closer aliases above. export type seeker = fn(s: stream, off: off, w: whence) (off | error);