I like the structure of streams wrapping streams from the point of view of modularity of implementation and flexibility of reuse (as in applying buffering and encoding to in-memory or network streams).
But I don’t like exposing al the machinery to the user. For example, instead of bufferedReadStream := ZnBufferedReadStream on: aReadStream. bufferedWriteStream := ZnBufferedWriteStream on: aWriteStream. why not bufferedReadStream := ZnBuffer on: aReadStream. bufferedWriteStream := ZnBuffer on: aWriteStream where the class that implements the buffering looks at the stream and decides whether to do read or write buffering (or both, for a read-write stream). The meaning of #position: on an encoded Unicode stream is perfectly well-defined. It’s just not the same as the meaning of position on the underlying byteStream — one counts in codePoints, the other in bytes. The old file streams got this wrong; I’m hoping that the new ones get it right. However, the comment that "As a side note: using #size and #position[:] on variable encoded streams like UTF8 is *very* dangerous and should be avoided.” makes me worry that they do not. Please, either implement #size and #position[:] correctly on the encoded stream, or don’t implement them at all! Do *not* implement them incorrectly, and then tell me to avoid them because they are dangerous! Andrew