This commit makes a few changes to the Sink implementation on Framed:
* Backpressure is implemented for `start_send`. If the write buffer is
over 8KiB and can't be flushed, no new items are accepted.
* 0 length writes to the upstream transport are translated into a
`WriteZero` error, as with `io::Write::write_all`. `write_all` checks
for and ignores `Interrupted` errors, but I do not think this is
necessary for non-blocking writes.
* In `poll_complete`, the upstream transport is not flushed until
*after* writing the entire write buffer.
traits into `Codec`
A previous commit refactored such that `Encode` and `Decode` are
implemented directly on the types being encoded or decoded. This was
thought to be less expressive but more convenient than having a separate
notion of a (stateful) encoder or decoder.
However, there are certain situations where the approach is just too
limiting: you're required to implemented `Decode` and `Encode` for types
you don't "own" and can't newtype.
This commit moves back to a setup where `Self` represents the
encoder/decoder state; it also merges the two traits into a single
`Codec` trait, since they are currently always used together.
- Gets rid of `easy` module, instead providing framing support directly
in the `io` module.
- In particular, adds a framing adapter directly to the `Io` trait,
which gives you a Stream + Sink object. That object can then be
`split` into separate `Stream` and `Sink` objects if needed.
- Deprecates the `FramedIo` trait; that's now just Stream + Sink.
- Updates the line framing test to use the stream/sink combinators.
Typically this happens automatically as the `E` in `PollEvented<E>` is an owned
reference (e.g. a `TcpStream`) where dropping that will close the resource,
automatically unregistering it from the event loop. In some situations, however,
this isn't always the case, so the deregistering needs to happen manually.
This commit makes a few tweaks to the new `easy` module:
- Rename `Parse` to `Decode`, and `Serialize` to `Encode`.
- Don't use `Poll` for the `decode` method; we prefer to reserve
that type for actual aync events, and in particular for a `NotReady`
result to imply that some task scheduling has taken place. Instead,
use an internal `Option`.