Module io/stdio

io/stdio
Stability: unstable — the offset field is the open question, and it is a bug before it is a design (see the paragraph above). The fix is likely to REMOVE per-handle offsets for the standard streams and let the kernel's own file offset apply, which changes no signature in this file but does change observable behaviour, so freezing before that would freeze the clobber. A second, smaller question rides along: Rust's `io::stdout()` returns a handle to ONE shared, locked stream, while `stdout()` here returns an independent object each time — if the offsets go away the two become equivalent, and if they do not, this needs to become a singleton. The three types, the three accessors and the `fd()` methods are expected to keep their names. — stable modules only change additively; this one may still change.

Typed standard-stream handles — stdin() / stdout() / stderr() (plans/archive/STD_API_AUDIT.md §D5).

Each handle wraps its well-known file descriptor (0/1/2) and implements the async Reader/Writer traits from std/io, so code written against the traits works on the standard streams the same way it works on a File or a TcpStream. This is the typed replacement for the BufReader.new(i32(0)) magic number.

The handles are UNBUFFERED: every read/write is one async syscall. Each handle keeps a sequential offset the way std/sys/bufio does — required when a standard stream is REDIRECTED to a regular file (the async runtime writes positionally there); for pipes and terminals the offset is ignored.

That offset is per HANDLE, and stdout() mints a new one starting at zero on every call — so two handles overwrite each other when stdout is redirected to a file, and so does mixing a handle with std/fmt's println (which writes through libc's own buffered stdio and flushes at exit). To a pipe or a terminal both work, which is what makes this easy to miss. Until it is fixed, pick ONE writer per stream for the lifetime of the process: keep a single handle and pass it around, and do not interleave println with it (issues/stddoc-io-stdio-handles-write-positionally-and-clobber-redirected-output.md).

There is no write_string here: the handles carry exactly the trait surface, whose write/write_all take a raw *(u8), so writing text from safe code goes through BufWriter(Stdout) (which has write_string/write_bytes) or through std/fmt. Likewise the line primitive for input is BufReader(Stdin).read_line, not a method here.

Stability

unstable — the offset field is the open question, and it is a bug before it is a design (see the paragraph above). The fix is likely to REMOVE per-handle offsets for the standard streams and let the kernel's own file offset apply, which changes no signature in this file but does change observable behaviour, so freezing before that would freeze the clobber. A second, smaller question rides along: Rust's io::stdout() returns a handle to ONE shared, locked stream, while stdout() here returns an independent object each time — if the offsets go away the two become equivalent, and if they do not, this needs to become a singleton. The three types, the three accessors and the fd() methods are expected to keep their names.

Types

Stdin object
Stdin

The process's standard input (fd 0).

Fields

NameTypeDescription
_offsetu64

Trait Implementations

impl(Stdin, ...)
fd : (Stdin) fn(self : Stdin) -> i32

fd 2, for interop with fd-based APIs.

Parameters

NameTypeNotes
selfStdin

Returns: i32

impl(Stdin, Reader(...))
read : (Stdin) fn(self : Stdin, buf : *(u8), size : usize, io : Io) -> Impl : (Future[Future](usize) IoExn : IoExn)

Read up to size bytes into buf. Resolves to the number of bytes actually read; 0 means end-of-stream. Throws IoExn on failure.

Parameters

NameTypeNotes
selfStdin
buf*(u8)
sizeusize
ioIo

Returns: Impl : (Future[Future](usize) IoExn : IoExn)

Methods
read_to_end : (Stdin) fn(self : Stdin, io : Io) -> Impl : (Future[Future](ArrayList(u8)) IoExn : IoExn)

Read until end-of-stream, resolving to all remaining bytes. Loops the raw read with an internal chunk buffer, so implementors get it for free and callers never touch a raw pointer.

Parameters

NameTypeNotes
selfStdin
ioIo

Returns: Impl : (Future[Future](ArrayList(u8)) IoExn : IoExn)

read_to_string : (Stdin) fn(self : Stdin, io : Io) -> Impl : (Future[Future](String) IoExn : IoExn)

Read until end-of-stream and decode as UTF-8. Unlike the UNCHECKED per-type conveniences that predate D5, this validates: malformed bytes throw IoError.InvalidData (use read_to_end + String.from_utf8 to see the exact offset).

Parameters

NameTypeNotes
selfStdin
ioIo

Returns: Impl : (Future[Future](String) IoExn : IoExn)

Stdout object
Stdout

The process's standard output (fd 1).

Fields

NameTypeDescription
_offsetu64

Trait Implementations

impl(Stdout, ...)
fd : (Stdout) fn(self : Stdout) -> i32

fd 2, for interop with fd-based APIs.

Parameters

NameTypeNotes
selfStdout

Returns: i32

impl(Stdout, Writer(...))
write : (Stdout) fn(self : Stdout, buf : *(u8), size : usize, io : Io) -> Impl : (Future[Future](usize) IoExn : IoExn)

Write up to size bytes from buf. Resolves to the number of bytes actually written (which may be less than size). Throws IoExn on failure.

Parameters

NameTypeNotes
selfStdout
buf*(u8)
sizeusize
ioIo

Returns: Impl : (Future[Future](usize) IoExn : IoExn)

flush : (Stdout) fn(self : Stdout, io : Io) -> Impl : (Future[Future](unit) IoExn : IoExn)

Flush any buffered bytes through to the underlying sink. Unbuffered writers resolve immediately.

Parameters

NameTypeNotes
selfStdout
ioIo

Returns: Impl : (Future[Future](unit) IoExn : IoExn)

Methods
write_all : (Stdout) fn(self : Stdout, buf : *(u8), size : usize, io : Io) -> Impl : (Future[Future](unit) IoExn : IoExn)

Write ALL size bytes from buf, looping the raw write over short counts. Throws IoError.WriteZero if the sink stops accepting bytes before everything is delivered.

Parameters

NameTypeNotes
selfStdout
buf*(u8)
sizeusize
ioIo

Returns: Impl : (Future[Future](unit) IoExn : IoExn)

Stderr object
Stderr

The process's standard error (fd 2).

Fields

NameTypeDescription
_offsetu64

Trait Implementations

impl(Stderr, ...)
fd : (Stderr) fn(self : Stderr) -> i32

fd 2, for interop with fd-based APIs.

Parameters

NameTypeNotes
selfStderr

Returns: i32

impl(Stderr, Writer(...))
write : (Stderr) fn(self : Stderr, buf : *(u8), size : usize, io : Io) -> Impl : (Future[Future](usize) IoExn : IoExn)

Write up to size bytes from buf. Resolves to the number of bytes actually written (which may be less than size). Throws IoExn on failure.

Parameters

NameTypeNotes
selfStderr
buf*(u8)
sizeusize
ioIo

Returns: Impl : (Future[Future](usize) IoExn : IoExn)

flush : (Stderr) fn(self : Stderr, io : Io) -> Impl : (Future[Future](unit) IoExn : IoExn)

Flush any buffered bytes through to the underlying sink. Unbuffered writers resolve immediately.

Parameters

NameTypeNotes
selfStderr
ioIo

Returns: Impl : (Future[Future](unit) IoExn : IoExn)

Methods
write_all : (Stderr) fn(self : Stderr, buf : *(u8), size : usize, io : Io) -> Impl : (Future[Future](unit) IoExn : IoExn)

Write ALL size bytes from buf, looping the raw write over short counts. Throws IoError.WriteZero if the sink stops accepting bytes before everything is delivered.

Parameters

NameTypeNotes
selfStderr
buf*(u8)
sizeusize
ioIo

Returns: Impl : (Future[Future](unit) IoExn : IoExn)

Functions

stdin function
fn() -> Stdin

Handle to standard input.

Returns: Stdin

stdout function
fn() -> Stdout

Handle to standard output.

Returns: Stdout

stderr function
fn() -> Stderr

Handle to standard error.

Returns: Stderr