Description
Sink and Source provide methods to read and write data; for some of them, the behavior could be unclear from the name itself. The naming could be improved to make what to expect from different methods more obvious.
Here is a table describing methods and their behavior:
Method | Behavior |
---|---|
RawSource::read(sink: Buffer, bytesCount: Long): Long |
reads up to byteCount bytes into sink and returns the number of bytes read, or -1 if the source is exhausted |
Source::read(sink: ByteArray, offset: Int, byteCount: Int): Int |
reads up to byteCount bytes and writes it into sink starting at offset , returns the number of bytes read, or -1 if the source is exhausted |
Source::readFully(sink: RawSink, byteCount: Long): Unit |
reads byteCount bytes from the source and writes it into sink , throws exception if there are not enough data in the source |
Source::readAll(sink: RawSink): Long |
Reads all data until exhaustion and writes it into sink , return the number of bytes read |
Source::readFully(sink: ByteArray) |
Reads sink.length bytes from from the source |
Source::readByteArray() |
Reads all data from the source into a newly allocated array |
Source::readByteArray(byteCount: Long): ByteArray |
Reads byteCount bytes from the source into newly allocated array |
RawSink::write(source: Buffer, byteCount: Long) |
writes byteCount bytes from source |
Sink::write(source: ByteArray, offset: Int, byteCount: Int): Sink |
writes byteCount bytes from source starting from offset |
Sink::writeAll(source: RawSource): Long |
reads data from source until its exhaustion and writes it to this sink, return the number of bytes written |
Sink::write(source: RawSource, byteCount: Long): Sink |
reads byteCount bytes from source and writes into this sink, throws whatever exception source will throw during the read |
There are some inconsistencies in the behavior of read/write method pairs, as well as in their naming:
Source::read(sink: ByteArray, offset: Int, byteCount: Int): Int
is a unix-style read method that does not guarantee that the whole array's slice will be filled but instead returns how many bytes were actually read. Corresponding write-method,Sink::write(source: ByteArray, offset: Int, byteCount: Int): Sink
, unlike it's unix ancestor, writes the whole slice.Source::readFully(sink: RawSink, byteCount: Long): Unit
containsFully
in the name, it's write counterpart,Sink::write(source: RawSource, byteCount: Long): Sink
, doesn't.- At the same time, there are
readAll
writewriteAll
methods, which do conceptually the same thing asreadFully/write
, but use a different naming convention.
The behavior of Source::read(sink: ByteArray, offset: Int, byteCount: Int): Int
and Sink::write(source: ByteArray, offset: Int, byteCount: Int): Sink
mimics java.io.InputStream/OutputStream
, so leaving names and behavior without any changes might be OK. Also, there are extension functions to fill the whole array with data.
However, other functions may have names allowing to distinguish them from each other and to provide a more obvious hint regarding expected behavior.
I looked at some other IO libraries, and here are the naming conventions adopted there:
- to read exactly N bytes of data: java.io.InputStream::readNBytes, System.IO.Stream::readExactly, std::io::Read::read_exact
- to copy all data from a source to a sink: java.io.InputStream::transferTo, System.IO.Stream::CopyTo
I'm suggesting the following rename:
Old name | New name |
---|---|
Source::read(sink: ByteArray, offset: Int, byteCount: Int): Int |
don't change |
Source::readFully(sink: RawSink, byteCount: Long): Unit |
Source::readExactly(sink: RawSink, byteCount: Long): Unit |
Source::readFully(sink: ByteArray) |
Source::readExactly(sink: ByteArray) |
Source::readAll(sink: RawSink): Long |
Source::readAllTo(sink: RawSink): Long |
Sink::write(source: ByteArray, offset: Int, byteCount: Int): Sink |
don't change |
Sink::writeAll(source: RawSource): Long |
Sink::writeAllFrom(source: RawSource): Long |
Sink::write(source: RawSource, byteCount: Long): Sink |
don't change |
Write methods, except writeAll
, have the same behavior so they could have the same name; readExactly
better describes the operation compared to readFully
; readAllTo
/writeAllFrom
additionally stress out the direction of an operation.
Your opinion will be welcomed if you have better ideas regarding the naming.