All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.lightningkite.lightningdb.MySealedClassSerializer.kt Maven / Gradle / Ivy

@file:OptIn(InternalSerializationApi::class, ExperimentalSerializationApi::class)

package com.lightningkite.lightningdb

import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlinx.serialization.internal.GeneratedSerializer
import kotlinx.serialization.json.JsonNames
import kotlin.IllegalStateException
import kotlin.reflect.KClass

interface MySealedClassSerializerInterface: KSerializer {
    val serializerMap: Map>
}

public class MySealedClassSerializer(
    serialName: String,
    val baseClass: KClass,
    private val getSerializerMap: () -> Map>,
    val alternateReadNames: Map = mapOf(),
    val annotations: List = listOf(),
    val getName: (T) -> String
) : MySealedClassSerializerInterface {

    override val serializerMap by lazy { getSerializerMap() }
    private val indexToName by lazy { serializerMap.keys.toTypedArray() }
    private val nameToIndex by lazy {
        val map = HashMap()
        indexToName.withIndex().forEach { map[it.value] = it.index }
        alternateReadNames.forEach {
            map[it.value]?.let { o -> map[it.key] = o }
        }
        map
    }
    private val serializers by lazy { indexToName.map { serializerMap[it]!! }.toTypedArray() }
    private fun getIndex(item: T): Int = nameToIndex[getName(item)]
        ?: throw IllegalStateException("No serializer inside ${descriptor.serialName} found for ${getName(item)}; available: ${indexToName.joinToString()}")

    override val descriptor: SerialDescriptor = defer(serialName, StructureKind.CLASS) {
        buildClassSerialDescriptor(serialName) {
            this.annotations = [email protected]
            val reversedAlternates = alternateReadNames.entries.groupBy { it.value }.mapValues { it.value.map { it.key } }
            for ((index, s) in serializers.withIndex()) {
                element(s.descriptor.serialName, s.descriptor, isOptional = true, annotations = indexToName[index].let { reversedAlternates[it] }
                    ?.let { listOf(JsonNames(*it.toTypedArray())) } ?: listOf())
            }
        }
    }

    override fun deserialize(decoder: Decoder): T {
        return decoder.decodeStructure(descriptor) {
            val index = decodeElementIndex(descriptor)
            if (index == CompositeDecoder.DECODE_DONE) throw SerializationException("Single key expected, but received none.")
            if (index == CompositeDecoder.UNKNOWN_NAME) throw SerializationException("Unknown key received.")
            val result = decodeSerializableElement(descriptor, index, serializers[index])
            if(decodeElementIndex(descriptor) != CompositeDecoder.DECODE_DONE) throw SerializationException("Single key expected, but received multiple.")
            result
        }
    }

    override fun serialize(encoder: Encoder, value: T) {
        encoder.encodeStructure(descriptor) {
            val index = getIndex(value)
            @Suppress("UNCHECKED_CAST")
            this.encodeSerializableElement(descriptor, index, serializers[index] as KSerializer, value)
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy