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

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

package com.lightningkite.lightningdb

import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.SetSerializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.descriptors.SerialKind
import kotlinx.serialization.descriptors.capturedKClass
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.SerializersModuleBuilder
import kotlinx.serialization.modules.contextual
import kotlin.reflect.KClass
import kotlin.reflect.full.memberProperties

abstract class WrappingSerializer(val name: String): KSerializer {
    abstract fun getDeferred(): KSerializer
    abstract fun inner(it: OUTER): INNER
    abstract fun outer(it: INNER): OUTER
    val to by lazy { getDeferred() }
    override val descriptor: SerialDescriptor = LazyRenamedSerialDescriptor(name) { to.descriptor }
    override fun deserialize(decoder: Decoder): OUTER = outer(decoder.decodeSerializableValue(to))
    override fun serialize(encoder: Encoder, value: OUTER) =
        encoder.encodeSerializableValue(to, inner(value))
}

fun KSerializer<*>.listElement(): KSerializer<*>? {
    if(this is WrappingSerializer<*, *>) return this.to.listElement()
    val inner = this.nullElement() ?: this
    val theoreticalMethod = inner::class.java.methods.find { it.name.contains("getElementSerializer") } ?: return null
    return theoreticalMethod.invoke(inner, inner) as KSerializer<*>
}

fun KSerializer<*>.mapKeyElement(): KSerializer<*>? {
    if(this is WrappingSerializer<*, *>) return this.to.mapKeyElement()
    val inner = this.nullElement() ?: this
    val theoreticalMethod = inner::class.java.methods.find { it.name.contains("getKeySerializer") } ?: return null
    return theoreticalMethod.invoke(inner) as KSerializer<*>
}
fun KSerializer<*>.mapValueElement(): KSerializer<*>? {
    if(this is WrappingSerializer<*, *>) return this.to.mapValueElement()
    val inner = this.nullElement() ?: this
    val theoreticalMethod = inner::class.java.methods.find { it.name.contains("getValueSerializer") } ?: return null
    return theoreticalMethod.invoke(inner) as KSerializer<*>
}

fun KSerializer<*>.nullElement(): KSerializer<*>? {
    try {
        val type = this::class.java
        if(!type.name.contains("Null")) return null
        val theoreticalMethod = this::class.java.getDeclaredField("serializer")
        try { theoreticalMethod.isAccessible = true } catch(e: Exception) {}
        return theoreticalMethod.get(this) as KSerializer<*>
    } catch(e: Exception) { return null }
}

fun SerialDescriptor.nullElement(): SerialDescriptor? {
    try {
        val theoreticalMethod = this::class.java.getDeclaredField("original")
        try { theoreticalMethod.isAccessible = true } catch(e: Exception) {}
        return theoreticalMethod.get(this) as SerialDescriptor
    } catch(e: Exception) { return null }
}

@OptIn(ExperimentalSerializationApi::class)
internal fun defer(serialName: String, kind: SerialKind, deferred: () -> SerialDescriptor): SerialDescriptor = object : SerialDescriptor {

    private val original: SerialDescriptor by lazy(deferred)

    override val serialName: String
        get() = serialName
    override val kind: SerialKind
        get() = kind
    override val elementsCount: Int
        get() = original.elementsCount

    override fun getElementName(index: Int): String = original.getElementName(index)
    override fun getElementIndex(name: String): Int = original.getElementIndex(name)
    override fun getElementAnnotations(index: Int): List = original.getElementAnnotations(index)
    override fun getElementDescriptor(index: Int): SerialDescriptor = original.getElementDescriptor(index)
    override fun isElementOptional(index: Int): Boolean = original.isElementOptional(index)

    @ExperimentalSerializationApi
    override val annotations: List
        get() = original.annotations

    @ExperimentalSerializationApi
    override val isInline: Boolean
        get() = original.isInline

    @ExperimentalSerializationApi
    override val isNullable: Boolean
        get() = original.isNullable
}

internal fun  defer(deferred: () -> KSerializer): KSerializer = object : KSerializer {

    private val original: KSerializer by lazy(deferred)

    override fun deserialize(decoder: Decoder): T = original.deserialize(decoder)

    override val descriptor: SerialDescriptor
        get() = original.descriptor

    override fun serialize(encoder: Encoder, value: T) {
        original.serialize(encoder, value)
    }
}

interface TypeArgSerialDescriptor : SerialDescriptor {

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy