Contingencies

A contingency is any situation occurring during an operation on a stream, caused by the stream’s state, that prevents this operation from reading or writing the requested number of bytes.

These situations do not violate the postconditions of the corresponding operations, as their postconditions never say that the requested number of bytes will indeed be processed.

Each stream operation that may encounter a contingency await-returns a type which is a specialization of capy::io_result. These objects can be destructured using a structured binding. The first binding of such destructuring is of type std::error_code. This binding, call it ec, is used to signal if and which contingency occured:

  • If ec == std::error_code{}, no contingency occurred.

  • Otherwise a contingency occurred. In order to determine which contingency occurred, compare ec to error conditions, in particular to capy::cond.

Reaching the end of stream is also a contingency (which can be interpreted as preventing an infinite read from proceeding).
The stream operations can still throw exceptions to indicate conditions unrelated to stream state that prevent these operations from satisfying their postconditions, such as failures to grow a buffer, or failure to allocate a coroutine frame.
Operations on streams often await-return capy::io_result<std::size_t> destructuring to [ec, n], where n represents the number of processed bytes. Upon a reported contingency, a non-zero n indicates the state of the partial or sometimes even a full read. When an inner operation reports a contingency, the outer operation usually processes its partial results before reporting the contingency itself.