Encoding value classes fails in Protocol Buffers
Describe the bug Attempting to encode value classes with default generated serializers fails using Protocol Buffers.
To Reproduce
fun main(){
ProtoBuf {}.encodeToByteArray(Example(1))
}
@Serializable
@JvmInline
value class Example(val raw : Int)
Expected behavior Encodes correctly as the base type like e.g. json does. Currently gives: Exception in thread "main" kotlinx.serialization.SerializationException: No tag in stack for requested element at kotlinx.serialization.protobuf.internal.ProtobufTaggedBase.popTag(ProtobufTaggedBase.kt:55) at kotlinx.serialization.protobuf.internal.ProtobufTaggedEncoder.encodeInline(ProtobufTaggedEncoder.kt:178)
Possibly related: https://github.com/Kotlin/kotlinx.serialization/issues/1774
Workaround: Write a custom serializer:
fun main(){
ProtoBuf {}.encodeToByteArray(Example(1))
}
@JvmInline
@Serializable(with = ExampleSerializer::class)
value class Example(val raw : Int)
object ExampleSerializer : KSerializer<Example> {
override val descriptor: SerialDescriptor
get() = Int.serializer().descriptor
override fun serialize(
encoder: Encoder,
value: Example
) {
encoder.encodeInt(value.raw)
}
override fun deserialize(decoder: Decoder): Example {
return Example(decoder.decodeInt())
}
}
Environment
- Kotlin version: 2.2.0
- Library version: 1.9.0
- Kotlin platforms: JVM
- Gradle version: 8
I reproduced the issue. Our protobuf encoder is not capable of serializing inline value classes as top-level objects, only as other objects fields. Which is definitely a bug.
Seems like it won't be a simple fix as I initially thought:
- we need to figure out how to deal with
Proto<Something>-annotated fields of inline value classes - the same as above, but for the case of nested inline values classes
- potentially, there might be the same issues for inline values classes that are fields of regular classes, we have to figure out something there too
- Kotlin might start supporting multi-field value classes at some point, it's worth considering them when addressing single-field value classes issue