An async reader which allows a closure to map the output of the inner async
reader into a new buffer. This allows things like compression/encryption to
be layered on top of a normal reader.
An async reader which allows a closure to observe the bytes being read as
they are ready. This has use cases such as hashing the output of a reader
without interfering with the actual content.