Swift is lacking general-purpose byte-oriented data streams, e.g. equivalents of the venerable java.io.Stream classes, C++'s iostreams [ick], Python's StreamReader... Instead we have a hodgepodge of stuff. These are just the ones I'm aware of:
- FoundationEssentials'
InputStreamandOutputStream, which are crude wrappers around older Objective-C classes. They use unsafe buffer pointers in their API, don't throw errors, and have a lot of other design problems. Honestly this API sucked even in 2001. - Foundation's
URLSessionDataTask(another Obj-C wrapper) can stream HTTP but the API is based on callbacks scheduled ondispatch queuesOperationQueues. - SystemPackage has
FileDescriptor, which also uses unsafe pointers and is limited to file I/O. - BinaryParsing has a modern Span-based API. I love this library but it focuses exclusively on reading sequential in-memory data.
- SwiftNIO of course has a ton of stream stuff, but it's a rather heavyweight library that's AFAIK oriented toward servers, so I haven't investigated it.
All of them have incompatible APIs. For complicated reasons my project is currently using four of these, and I keep having to write glue code to adapt one to the other.
It seems like a good idea to have some core protocols for data streams in the standard library, and perhaps some basic implementations, like streams to read/write in-memory buffers and a function to copy data from one stream to another. Stream implementations in other packages could then adopt these protocols, making life easier for their users.
The core requirements are pretty minimal; basically func read(into: inout RawOutputSpan) async throws for input streams, and func write(from: RawSpan) async throws -> Int for output. Do they even need close methods or will deinit do?
I'm sure nailing down these protocols would take months of bikeshedding, but it would be worth it!
PS: This is starting to sound like a pitch, but I'm not at that point yet so I'm putting this in Using Swift for now.