kotlinx-io icon indicating copy to clipboard operation
kotlinx-io copied to clipboard

Extensions for interop with platform-specific APIs

Open fzhinkin opened this issue 2 years ago • 2 comments
trafficstars

Currently (https://github.com/Kotlin/kotlinx-io/pull/136), kotlinx-io will only provide a bare minimum of extensions required for interop with Java-specific APIs:

  • functions to wrap j.i.InputStream and j.n.ReadableByteChannel into Source.
  • functions to wrap j.o.OutputStream and j.n.WritableByteChannel into Sink.
  • functions to read from and write to j.n.ByteBuffer and java.io streams.

At the moment, it seems like interaction with most other core Java APIs could be performed via java.io streams or java.nio channels and buffers, so it should be sufficient to cover most cases.

This issue opened to initiate a discussion on which extensions should be added additionally, not only for JVM but for other targets too.

fzhinkin avatar Jun 22 '23 10:06 fzhinkin

It's also worth revisiting names for JVM-specific Buffer extensions as some of them are confusing (compared to Source/Sink, where operations are more obvious, thanks to type names), like:

  • Buffer.readTo(out: OutputStream, byteCount: Long = size)
  • Buffer.write(input: InputStream, byteCount: Long): Buffer

We may need to add some currently missing extensions and change the receiver of others to one of Buffer's interfaces - Sink or Source.

fzhinkin avatar Jun 23 '23 12:06 fzhinkin

Some observations from looking on API doc:

  • all functions which accept Buffer (or interfaces) also accepts byteCount (readTo/readAtMostTo/write)
  • all functions which accept ByteArray also accepts startIndex and endIndex (readTo/readAtMostTo/write)
  • there is no copyTo which accepts ByteArray or ByteBuffer
  • there is no copyTo/readTo/transferTo which accepts ByteBuffer, only readAtMostTo/write/transferFrom
  • all functions which accepts ByteBuffer doesn't have any other arguments - may be provide byteCount=byteBuffer.remaining or even start/end indices - it depends on how ByteBuffer is used (relative vs absolute) access

Overall, there are following core functions to work with bulks of memory: readTo/readAtMostTo/write/copyTo/transferTo/transferFrom - ideally I think we should provide all of them for each primitive (where applicable), be it Buffer(and interfaces), ByteArray, ByteBuffer, InputStream/OutputStream and may be ByteChannel(ByteWriteChannel/ByteReadChannel). But then it can be too much :)

  • may be it's better not to introduce separate functions like Buffer.smth and Source.smth but do a check is Buffer and use fast path if so because I believe most of the APIs will use Source/Sink while under the hood they could have Buffer. This could also reduce public API a little. Also this will reduce confusion when there is declaration like Buffer.**(Buffer/ByteBuffer) as they will become Source.** and Sink.** which is additionally directly shows in which direction operation goes, and so only Buffer.copyTo will be additional functionality that is specific to Buffer

whyoleg avatar Jun 23 '23 16:06 whyoleg