Source src/silo:std.io
1##! Byte-oriented IO traits — `Read`, `Write`, `BufRead`, `Seek`, and the `SeekFrom` union. 2##! 3##! Generic code can be written against `(Read src)` / `(Write sink a 4##! | o)` today. Concrete impls on capability handles (filesystem 5##! files, TCP sockets, Console stdin/stdout) are deferred pending the 6##! typed-handle infrastructure; `io-copy` is a stub that panics until 7##! those impls exist. The default in-memory `Write` target is `Str` 8##! directly — Silo's `Str` is a mutable owned buffer. 9##! 10##! Buffer parameter and return types use `Bytes` today where the 11##! long-term shape is an `(Seq U8 _)` existential, and error positions 12##! use `Str` where a dedicated `IOError` union will live. Default 13##! method bodies for `.read-exact`, `.read-to-end`, `.read-to-str`, 14##! `.rewind`, `.stream-position`, `.seek-relative`, and the `BufRead` 15##! helpers land alongside the capability-handle impls. 16 17:use 18 :open core AnyUInt Bytes I64 Option Result Str U64 U8 Unit 19 :open effects.panic panic 20:end 21 22# si[impl io.read+1] 23## Read — fills a caller-supplied byte buffer from the underlying source. 24## `.read` returns the handle threaded through and the number of bytes read; 25## a return of `0` means end-of-stream. Effect-polymorphic: in-memory 26## readers carry no effect, file-backed handles carry `+FileSystem`, 27## network handles carry `+Tcp`/`+Udp`. 28:trait(pub) Read 29 ## Fill the caller-provided buffer; return the handle and bytes read. 30 ## Zero return MUST mean end-of-stream. 31 .read ( Self Bytes -> Self AnyUInt ) +eff 32:end 33 34# si[impl io.write+1] 35## Write — unified sink trait parameterised on the input element type `a` 36## and an associated output type `o` returned by `.finish`. Every writer 37## MUST implement the primitive `(Write Self Bytes | Self)`; blanket impls 38## cascade UTF-8 encoding for `Str`, `Codepoint`, and `Pattern`. `.write` 39## is all-or-fail: partial writes MUST raise via `+eff`. `.flush` defaults 40## to a no-op in the spec; the default body is elided here pending 41## handle impls. 42:trait(pub) Write a | o 43 ## Write the entire value or raise via `+eff`. Returns the handle on 44 ## success; there is no partial-write return. 45 .write ( Self a -> Self ) +eff 46 ## Push any buffered bytes downstream. Spec default is a no-op; concrete 47 ## impls override for streaming writers. 48 .flush ( Self -> Self ) +eff 49 ## Consume the writer and produce the associated output type. 50 .finish ( Self -> o ) +eff 51:end 52 53# si[impl io.bufread+1] 54## BufRead — Read plus buffer-aware operations. An implementation MUST 55## maintain an internal buffer that decouples application-level reads 56## from source-level reads. 57:trait(pub) BufRead { (Read Self) } 58 ## Fill and return a view of the internal buffer. 59 .fill-buf ( Self -> Self Bytes ) +eff 60 ## Mark `n` bytes of the internal buffer as consumed. 61 .consume ( Self AnyUInt -> Self ) 62 ## Read one line (UTF-8); returns the handle and a fallible Str. 63 .read-line ( Self -> Self (Result Str Str) ) +eff 64 ## Read up to and including the delimiter byte; returns the handle and 65 ## the collected bytes on success. 66 .read-until ( Self U8 -> Self (Result Bytes Str) ) +eff 67:end 68 69# si[impl io.seek] 70## SeekFrom — the offset origin. `Start` uses an unsigned offset (position 71## measured from beginning); `End` and `Current` use signed offsets because 72## relative positions may be negative. 73:union(pub) SeekFrom 74 | Start U64 75 | End I64 76 | Current I64 77:end 78 79# si[impl io.seek] 80## Seek — random-access positioning. Implemented by file handles and 81## in-memory byte buffers; network sockets MUST NOT implement Seek. 82:trait(pub) Seek 83 ## Move the position per `SeekFrom`; return the new absolute offset. 84 .seek ( Self SeekFrom -> Self (Result U64 Str) ) +eff 85:end 86 87# si[impl io.copy+1] 88## `io-copy` — copy bytes from any `Read` source to any `Write Bytes` sink 89## until end-of-stream on the source, returning the total bytes copied. 90## 91## The real implementation needs capability-handle impls of `Read` and 92## `Write` so the effect row can be resolved; until those land, the body 93## here panics. The signature is the spec signature with the existential 94## `(Seq U8 _)` replaced by `Bytes` (see divergence 1) and the effect 95## variable elided because no constraint can mention the `Read`/`Write` 96## impls' effect rows yet. 97:fn(pub) io-copy ( src sink -> src sink AnyUInt ) 98 "io-copy not implemented yet — awaits capability-handle Read/Write impls" panic 99:end