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.