Experimenting with new sync/async API.

This is closer to Node’s “Streams2” and supports both an asynchronous function
for file system operations and a synchronous function for in-memory operations.
Simplify end logic.
Logic tweaks.

Don’t need to check if the writer is available before writing, because we flush
after each write, which is guaranteed to empty the buffer and thus the writer
will always be available (for at least one write). Also, we always need to flush
before filling the reader, as filling the reader overwrites its buffer.

(If you want to flush and fill in parallel, you need to make a separate copy of
the read buffer so that it doesn’t get overwritten before the flush.)
Must signal end separately.

Can’t use available bytes to indicate end because it’s possible that only SOME
of the bytes will be read before the reader is refilled (e.g., in the case of a
fixed-sized record reader where the read buffer size is not a multiple of the
fixed record size).
Simplify.
TODO
Generic reader & writer.

Rename file-specific functions.
Fix additional writes after reader ends.

Also fix callback when open finishes before first write flush.
Pull out closures.
Add line parser.
Configurable encoding & buffer length.

Writers can now have an encoding, making it easier to convert strings to buffers
before writing. You can likewise configure the size of the internal buffers used
by readers and writers.

In a future commit, I think I need to change the behavior when the write buffer
overflows. I think returning null from read is okay for reading, but returning
null from write is awkward because it forces the client to save the rejected
input while the writer is flushed, and then subsequently re-write it.

I could have the writer stash the overflow (a single overflow buffer)
automatically and then clients would not need stash it. Alternatively the writer
could stash arbitrary amounts of overflow, and then clients need only observe
the return value of write as an advisory.
Make writer.write’s return value advisory.

Rather than copying the input data into a buffer, the writer now accumulates an
array of buffers to write. This makes writers easier to use, since you can use
the return value to detect when to stop writing, but the writer will still
remember to write the data that overflowed the buffer.

I’m still concerned that many, many calls to fs.write will be slower than
batching buffers into a single fs.write, but that’s easy enough to test without
changing the API. (The writer can simply concat the buffers prior to writing,
and could employ a simple heuristic, such as counting the number of buffers.)

Also, rename writer.flush to writer.drain for symmetry with fs.
Also, fix bug when changing reader.bufferLength.
Also, coerce and validate length argument to reader.read.
Also, if writer.write is given a non-buffer, it is string-coerce and encoded.
Fix buffer length checks.
Fix writer.write return value.
Cleaner rewrite?
Clearer?
Use 64K buffer.
Invoke open after constructor finishes.
Close the channel on error.
Add reader.end.

Also, re-throw any existing error if an error occurred and a subsequent
operation was requested.