What's the equivalent pattern for writing a tempor...
# io
k
What's the equivalent pattern for writing a temporary length prefix, delegating to some other code to encode something of unknown length, then backtracking to update the length prefix? i.e. something like this, with Netty's ByteBuf:
Copy code
// Length placeholder...
        int lengthStartIndex = buffer.writerIndex();
        buffer.writeShort(0);

        buffer.writeInt((int) packet.getSessionHandle());
        buffer.writeInt(packet.getStatus().getStatus());
        buffer.writeLong(packet.getSenderContext());
        buffer.writeInt(0);

        int dataStartIndex = buffer.writerIndex();

        if (packet.getCommand() != null) {
            encodeCommand(packet.getCommand(), buffer);
        }

        // Go back and update the length.
        int bytesWritten = buffer.writerIndex() - dataStartIndex;
        buffer.markWriterIndex();
        buffer.writerIndex(lengthStartIndex);
        buffer.writeShort(bytesWritten);
        buffer.resetWriterIndex();
do I need to instead allocate a new Buffer or let the other code return a Buffer and then deal with writing everything once I have it and know its size?
f
There's no way to update buffer's content in place. Both options you've mentioned should work. Personally, if possible, I would use the second option, where some client code returns a buffer with an encoded message and then I write its length and the buffer itself to a Sink.
k
I'll probably pass the buffer, I'd like to write the serialization codecs with signatures like this:
Copy code
object Serializer {
    
    fun encode(command: Command, sink: Sink) { TODO() }
    
    fun decode(source: Source): Command { TODO() }
    
}
the serializer embedding it then just ends up with something like:
Copy code
Buffer().apply {
    encodeCommand(CommandCode.NOP, this)
    
    sink.writeLong(size)   // encoded command length
    sink.write(this, size) // encoded command data
}
just trying to get a feel for the kotlinx-io APIs to see if I can replace Netty's ByteBuf
e
This is what I do. Code should be self-explanatory
Copy code
val serializableBuffer = Buffer()
val outputStream = BufferOutputStream(serializableBuffer, transcoder)
serializable.serialize(outputStream)

val packet = Buffer()

if (serializable.autosize()) {
  packet.writeInt(serializableBuffer.size.toInt())
}

packet.transferFrom(serializableBuffer)