kotlinx.serialization icon indicating copy to clipboard operation
kotlinx.serialization copied to clipboard

Add implementation for computing the required bytes to encode a message

Open GeorgePap-719 opened this issue 2 years ago • 5 comments

Summary

This commit introduces a new API which computes the required bytes to encode a message without actually serializing a message. The size is computed on the first call and memoized. By extension, this API is meant to be used as a cornerstone for implementing #2075.

Goal:

After feedback on #2082, the most critical problem we had to solve was how to make an actual streaming protobuf without reading all to byte array first. This API solves this problem, as we can calculate the required bytes to encode a message.

By extension, this pr acts as a proof of concept, and also as a base to enable discussions for #2075.

Implementation notes

API

The API which is introduced:

public fun <T : Any> ProtoBuf.getOrComputeSerializedSize(serializer: SerializationStrategy<T>, value: T): Int

Even though this API has some usage for consumers, for example see protobuf.js#162, it can also be considered as an internal API to support only encoding/decoding delimited-messages.

Tests

The main tests are written in jvm platform, because java's serializedSize API result is used to test against getOrComputeSerializedSize() result.

Multiplatform

Native and Js implementations do not use concurrent-safe structures.

Even though the core implementation is written in common module, it is tested only in jvm. In case we decide to keep this API in common then tests should be moved in common or re-think testing strategy.

Additionally, since the goal of this API is to be used as a cornerstone for a jvm only feature, it is debatable if the API really belongs to common module.

Inspiration

The inspiration came from how the official library (google's) solved this issue, in particular java's implementation. That being said, it is to be noted that many byte operations were "rented" from google's impl (some with minor modifications, some not). This is done to avoid re-inventing the wheel, and because i'm not so experienced to create them by myself.

GeorgePap-719 avatar Mar 17 '23 16:03 GeorgePap-719

@qwwdfsad (sorry for tag but since you were the reviewer of 2082, i figured to save some time) Take a look if you have time.

GeorgePap-719 avatar Mar 17 '23 16:03 GeorgePap-719

A vote for this.

ShreckYe avatar Mar 06 '24 04:03 ShreckYe

Hey @sandwwraith, I think it's time to take a look on this again. I think there are enough use-cases to go forward with this, as mentioned in #2075.

Let me know your opinion on this.

GeorgePap-719 avatar Jul 08 '24 17:07 GeorgePap-719

@GeorgePap-719 I will, but my hands are a bit full now, sorry :( Maybe it is a good idea to also consult with kotlinx.rpc team of whether this would be useful to them while supporting gRPC.

sandwwraith avatar Jul 08 '24 17:07 sandwwraith

No worries man! Ok, I will reach out to kotlinx.rpc team

GeorgePap-719 avatar Jul 09 '24 08:07 GeorgePap-719