IO Module
The io module provides byte streams and standard process streams. Filesystem
and path operations belong to std.fs.
Import
Byte streams
io.Reader and io.Writer are shared resource handles. Constructors take no
arguments; parameterized construction uses explicit from_*/to_* names.
Every fallible Reader/Writer operation returns result<value, IoError>.
IoError exposes read-only kind, detail, and operation fields, plus
message() and to_string().
-
io.stdin()returns a non-seekable reader over process standard input. -
io.stdout()returns a non-buffering writer over standard output. -
io.stderr()returns a non-buffering writer over standard error. -
reader.read_line()returns the next UTF-8 line without its LF/CRLF terminator, ornoneat EOF. A final unterminated line is returned normally; invalid UTF-8 and lines over 16 MiB are errors. -
io.Reader.new()creates an empty reader. -
io.Reader.from_bytes(bytes)creates a reader over a byte copy. -
io.Reader.from_file(string path)returns a reader backed by a live file stream; bytes are read incrementally rather than copied up front. -
io.Reader.from_tcp(net.TcpStream)returns a reader over a cloned TCP connection for incremental socket reads. -
reader.read(int limit)consumes up tolimitbytes. -
reader.limit(int limit)caps the total bytes returned by future reads. -
reader.tee(writer)duplicates future reads intowriter;untee()stops duplication. -
reader.read_exact(int size)errors if EOF arrives early. -
reader.remaining()reports unread bytes. -
reader.read_to_end(int limit)consumes all remaining bytes up tolimit. -
reader.copy_to(writer, int limit)copies up tolimitbytes into another writer and returns the count copied. -
reader.position()andreader.seek(int position)provide bounded cursor access. -
reader.close()releases the underlying file/socket resource and invalidates all aliases. -
io.Writer.new()creates an in-memory writer. -
io.Writer.to_file(string path)returns a writer that truncates and writes the destination file; callflush()to force buffered OS writes. -
io.Writer.append_file(string path)returns a writer that preserves the destination file and appends every write at its end. -
io.Writer.from_tcp(net.TcpStream)returns a writer over a cloned TCP connection for incremental socket writes. -
writer.write(bytes)appends and returns the number of bytes written. -
writer.write_all(bytes)appends all bytes and returnsresult<void, IoError>. -
writer.bytes()returns a copy of the accumulated bytes. -
writer.position()andwriter.seek(int position)provide bounded cursor access for in-memory and truncating file writers. Append-mode, socket, and standard-stream writers are not seekable. -
writer.flush()is an explicit, synchronous flush point. -
writer.close()releases the underlying file/socket resource and invalidates all aliases.
File-backed constructors preserve native open failures in IoError.kind (for
example not_found or permission) and identify the failed operation through
IoError.operation (reader.from_file, writer.to_file, or
writer.append_file).
Low-level file-handle writes reject null handles or content pointers and report
failure without dereferencing them; normal Mux code should use the typed
Reader and Writer APIs above.
Dropping the last reader name also releases a writer retained by reader.tee;
an explicit close() is not required solely to clean up a tee relationship.
Standard output/error writers stream directly to the process handles and do not
support writer.bytes(); call flush() when an explicit flush boundary is
needed. Closing a standard-stream handle does not close the process stream.
Reads are bounded to 16 MiB per operation, including whole-file reads exposed
by std.fs and the internal adapters used by other standard-library readers;
buffered writers are bounded to a 16 MiB
total buffer.
Stream capabilities
std.io also exports small interfaces for generic stream helpers. Import the
capabilities with import std.io.* and use them as generic bounds:
| Interface | Required methods | Implemented by |
|---|---|---|
Readable | read(int) -> result<bytes, IoError> | io.Reader, net.TcpStream, net.LocalStream, net.tls.TlsStream |
Writable | write(bytes) -> result<int, IoError> | io.Writer, net.TcpStream, net.LocalStream, net.tls.TlsStream |
Seek | position() -> result<int, IoError>, seek(int) -> result<int, IoError> | io.Reader, io.Writer |
The interfaces are capability contracts, not dynamic stream values. Calls are
statically dispatched after generic specialization, so a helper can accept any
current or future concrete type that implements the required methods. A
Reader or Writer may still return an error from Seek when its underlying
resource is not seekable (for example, standard input or a socket).
Erased streams
io.Stream is an owned, type-erased handle for code that needs to store
different stream implementations together. It keeps one capability. A read
operation on a writer, or a write operation on a reader, returns
IoError.kind == unsupported.
io.Stream.from_reader(reader)wraps aReadercapability.io.Stream.from_writer(writer)wraps aWritercapability.stream.read(int),stream.write(bytes),stream.flush(), andstream.seek(int)forward to the stored capability.stream.close()closes the erased handle and releases its owned capability.
Copies share the underlying capability and keep it alive until the last copy is
closed or dropped. The erased handle does not turn the static Readable,
Writable, or Seek interfaces into dynamic values. Use those interfaces as
generic bounds when the operation should be checked at compile time.