We'll use a common stream data structure for input and output streams.
Having separate types makes more sense in a more high-level language, where
we have type checking and where functions for handling the different types
are more concise. But in machine code the sweet spot is more toward fewer
types.
Extract a helper for appending strings to raw buffers.
I'd been resisting this idea, but it actually turns out to be a pretty
clean abstraction in the end.