
com.lightningkite.lightningdb.PartialSerializer.kt Maven / Gradle / Ivy
package com.lightningkite.lightningdb
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.descriptors.SerialKind
import kotlinx.serialization.descriptors.StructureKind
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
import kotlinx.serialization.encoding.*
import kotlinx.serialization.internal.GeneratedSerializer
import kotlin.reflect.KProperty1
@OptIn(InternalSerializationApi::class)
class PartialSerializer(source: KSerializer): KSerializer> {
val source = source as GeneratedSerializer
private val childSerializers = this.source.childSerializers().map {
if (it is GeneratedSerializer<*> && it.childSerializers().isNotEmpty()) {
PartialSerializer(it)
} else it
}
override val descriptor: SerialDescriptor
get() {
try {
val sourceDescriptor = source.descriptor
return buildClassSerialDescriptor("com.lightningkite.lightningdb.Partial", sourceDescriptor) {
for (index in 0 until sourceDescriptor.elementsCount) {
val s = childSerializers[index]
if (s is PartialSerializer<*>) {
element(
elementName = sourceDescriptor.getElementName(index),
descriptor = s.descriptor,
annotations = sourceDescriptor.getElementAnnotations(index),
isOptional = true
)
} else {
element(
elementName = sourceDescriptor.getElementName(index),
descriptor = sourceDescriptor.getElementDescriptor(index),
annotations = sourceDescriptor.getElementAnnotations(index),
isOptional = true
)
}
}
}
} catch(e: Exception) {
throw Exception("Failed to make partial descriptor for ${source.descriptor.serialName}", e)
}
}
override fun deserialize(decoder: Decoder): Partial = decoder.decodeStructure(descriptor) {
val out = HashMap()
while (true) {
when (val index = decodeElementIndex(descriptor)) {
CompositeDecoder.DECODE_DONE -> break
CompositeDecoder.UNKNOWN_NAME -> continue
else -> out[descriptor.getElementName(index)] = decodeSerializableElement(descriptor, index, childSerializers[index])
}
}
Partial(out)
}
override fun serialize(encoder: Encoder, value: Partial) = encoder.encodeStructure(descriptor) {
for((key, v) in value.parts) {
val index = descriptor.getElementIndex(key)
encodeSerializableElement(descriptor, index, childSerializers[index] as KSerializer, v)
}
}
}
fun DataClassPathPartial.setMap(key: K, out: Partial) {
if(properties.isEmpty()) throw IllegalStateException("Path ${this} cannot be set for partial")
var current = out as Partial
for (prop in properties.dropLast(1)) {
current = current.parts.getOrPut(prop.name) { Partial() } as Partial
}
current.parts[properties.last().name] = getAny(key)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy