Questions / proposal for the IO abstractions
Hello,
As you well know the io
abstractions are a critical piece of a language, and taking a closer look at the existing io.inko
file I had some questions and propositions about it.
Read and Write
Both the Read
and Write
traits work with strings as fundamental type, and looking at the string.inko
file it mentions that strings are always utf-8, so the existing IO traits are not suitable for binary data. Maybe the current traits were added as a stopgap measure to support stdin/err/out and you have other plans for a more general abstraction? In any case, I'd suggest to use bytes as fundamental type (well, integers representing bytes I guess?) to support binary and utf-8 text. The traits could then easily implement methods for strings that call the bytes version.
Read trait
The Read.read
method reads until EOF and is a method to implement on each reader, but that seems impractical as some readers will be unbounded streams (e.g. sockets).
I feel like the central Read
method should be what is currently read_exact
(more on this later), and read
that reads the full data should be implemented by the trait as a series of calls to read_exact
until EOF.
Regarding the name of read_exact
, I think it should be renamed read_up_to
(or read_at_most
?), given that the returned string (bytes) may be less than the requested amount. The current name suggests that the callee will retry until it reads that many bytes exactly, and throw otherwise (e.g. ShortReadError
).
Write trait
Other than using bytes instead of strings, I was wondering if flush
shouldn't be its own separate trait? I.e. when writing directly (unbuffered) to a socket, flush wouldn't be required (nor to a file, unless that would expose the low-level fsync
but I doubt that's the goal here). Buffered writers would implement the Flush
trait. Also, did you have plans to add formatted IO in the stdlib?
Close trait
I noticed the close
method does not throw, but for writers, the close
system call can fail with EIO
and that can matter to the program (i.e. data loss). I think it should be defined as throwable.
Seek trait
Typically, the seek call supports seeking from the start, current or end position (the whence
parameter), it would be useful to expose this in the trait?
Thanks, Martin