Writing to the process's standard error, and the typed outcome of a write.
Standard error is where an app says something went wrong while standard
output is carrying the answer someone is piping elsewhere, so a diagnostic
does not corrupt the data stream. Everything else about it -- the bound, the
phases, the newline, the absence of buffering -- is the same as Stdout,
and the two are deliberately interchangeable at the call site.
These effects are queued. A call copies the bytes into a host-owned queue of
its own -- the two streams do not share one -- and returns; one host thread
drains both queues and does the writing. Every one of them is legal in
init!, in update!, and in tasks; they are refused in render!, with a
message naming the effect and the fix. Standard error is usually unbuffered
and usually a terminal, but it can be redirected into a pipe like any other
descriptor, and the queue is what keeps that off the frame thread:
The queue holds 256 kibibytes, which is also the largest a single payload can
be. A payload past that is TooLarge; one that does not fit right now is
BufferFull with nothing queued, so a refusal never leaves half a line in
the pipe. What is queued when the app exits is drained before the process
does, so a diagnostic written in the same update! that returns
Err(Exit(1)) still reaches the terminal.
The compiler's own dbg, expect, and crash output also goes here, written
directly by the runtime rather than through this module. Ordering between
the two is not defined, and this module is the app's channel rather than a
replacement for either.
Legal in init!, update!, and tasks; refused in render!.
The newline is always a single \n, on every platform. The text and its
terminator are queued together, so nothing else can land between them. At
most 256 kibibytes cross per call, counting the string's UTF-8 bytes and
the newline; a longer string is TooLarge and nothing is queued.
Legal in init!, update!, and tasks; refused in render!.
The bytes are passed through as they are: no encoding validation, no
newline, no translation. Bounded exactly as line! is, counting the length
of the list.
Why a write to standard error was not queued. This is this module's
own WriteError; Files declares a different one under the same
name, for the different things a file write can refuse.
BufferFull is the queue having no room for this payload right now, and
nothing was queued; the drainer is behind, and the same call may succeed
a moment later. TooLarge is a payload bigger than the whole queue,
which no amount of draining will ever fit. Unavailable is there being
no queue to write into: the reader on the other end has gone away, which
is an ordinary way for a pipeline to end, or the host is shutting down.