I'm looking into the source code for Okio in order to understand efficient byte transferring better, and as a toy example made a little ForwardingSource
which inverts individual bytes as they come along. For example, it transforms (unsigned) 0b1011
to (unsigned) 0b0100
.
class ByteInvertingSource(source: Source) : ForwardingSource(source) {
// temporarily stores incoming bytes
private val sourceBuffer: Buffer = Buffer()
override fun read(sink: Buffer, byteCount: Long): Long {
// read incoming bytes
val count = delegate.read(sourceBuffer, byteCount)
// write inverted bytes to sink
sink.write(
sourceBuffer.readByteArray().apply {
println("Converting: ${joinToString(",") { it.toString(2) }}")
forEachIndexed { index, byte -> this[index] = byte.inv() }
println("Converted : ${joinToString(",") { it.toString(2) }}")
}
)
return count
}
}
Is this optimal code?
Specifically:
sourceBuffer
field, or could I use another trick to transform the bytes directly?sourceBuffer
and write the individual bytes into sink
? (I can't find a write(Byte)
method, so maybe that is a clue that it's not.)It looks pretty close the this testing sample from OkHttp.
override fun read(
sink: Buffer,
byteCount: Long
): Long {
val buffer = Buffer()
val read = delegate.read(buffer, byteCount)
if (read != -1L) {
sink.write(buffer.readByteString().toAsciiUppercase())
}
return read
}
It is definitely not more efficient to read individual bytes. I don't think you can improve your invert loop, as it's an operation on a single byte. But generally you don't want to be doing loops in your code, so definitely do the bulk reads.