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

commonMain.com.caesarealabs.rpc4k.runtime.implementation.serializers.Rpc4kSerializers.kt Maven / Gradle / Ivy

package com.caesarealabs.rpc4k.runtime.implementation.serializers

import com.benasher44.uuid.Uuid
import com.caesarealabs.rpc4k.runtime.implementation.KotlinClassName
import com.caesarealabs.rpc4k.runtime.implementation.KotlinMethodName
import com.caesarealabs.rpc4k.runtime.implementation.KotlinName
import kotlinx.serialization.KSerializer
import kotlinx.serialization.modules.SerializersModule
import kotlin.reflect.KClass

// Used for the processor only
public val Rpc4kSerializers: List> = Rpc4kSerializersModuleBuilder().apply {
    obj(VoidUnitSerializer, "kotlin", "Unit", "com.caesarealabs.rpc4k.runtime.implementation.serializers", "VoidUnitSerializer")
    obj(UUIDSerializer, "com.benasher44.uuid","Uuid","com.caesarealabs.rpc4k.runtime.implementation.serializers", "UUIDSerializer")
    // Use our serializer for the java UUID as because the MP UUID is typealiased to it
    obj(UUIDSerializer, "java.util","UUID","com.caesarealabs.rpc4k.runtime.implementation.serializers", "UUIDSerializer")
//    obj(InstantIsoSerializer)
//    obj(ZonedDateTimeIsoSerializer)
    builtinSerializerMethod(Pair::class, "kotlin", "Pair", "TuplePairSerializer") {
        TuplePairSerializer(it[0], it[1])
    }
    builtinSerializerMethod(Triple::class, "kotlin", "Triple", "TupleTripleSerializer") {
        TupleTripleSerializer(it[0], it[1], it[2])
    }
    builtinSerializerMethod(Map.Entry::class, "kotlin.collections", "Map.Entry", "TupleMapEntrySerializer") {
        TupleMapEntrySerializer(it[0], it[1])
    }
}.build()

@Suppress("UNCHECKED_CAST")
public val Rpc4kSerializersModule: SerializersModule = SerializersModule {
    for (serializer in Rpc4kSerializers) {
        when (val provider = serializer.provider) {
            is ContextualProvider.Argless -> contextual(serializer.serializedKClass as KClass, provider.serializer as KSerializer)
            is ContextualProvider.WithTypeArguments -> contextual(serializer.serializedKClass, provider.provider)
        }
    }
}

// This could become a public api in the future
private class Rpc4kSerializersModuleBuilder {
    @PublishedApi
    internal val serializers = mutableListOf>()

    /**
     * Class names are passed explicitly for type aliases to work
     */
    fun  method(
        kClass: KClass,
        typePackage: String,
        typeName: String,
        serializerName: String,
        serializerPackage: String,
        provider: (typeArgumentsSerializers: List>) -> KSerializer<*>
    ) {
        serializers.add(
            Rpc4kSerializer.Function(
                KotlinMethodName(serializerName, serializerPackage), ContextualProvider.WithTypeArguments(provider), kClass,
                KotlinClassName(pkg = typePackage, simple = typeName)
            )
        )
    }

    /**
     * Class names are passed explicitly for type aliases to work
     */
    inline fun  obj(
        instance: KSerializer,
        typePackage: String,
        typeName: String,
        serializerPackage: String,
        serializerName: String
    ) {
        serializers.add(
            Rpc4kSerializer.Object(
                KotlinClassName(simple = serializerName, pkg = serializerPackage),
                ContextualProvider.Argless(instance),
                T::class,
                KotlinClassName(simple = typeName, pkg = typePackage)
            )
        )
    }

//    @PublishedApi
//    internal fun  add(qualifiedName: KotlinName, provider: ContextualProvider, kind: Rpc4kSerializer.Kind, kClass: KClass) {
//        serializers.add(Rpc4kSerializer(qualifiedName, provider, kind, kClass))
//    }
//
//    @PublishedApi
//    internal inline fun  add(name: KotlinName, provider: ContextualProvider, kind: Rpc4kSerializer.Kind) {
//        add(name, provider, kind, T::class)
//    }

//    @PublishedApi
//    internal inline fun  method(name: KotlinName, provider: ContextualProvider) {
//        add(name, provider, Rpc4kSerializer.Kind.Method)
//    }

    internal fun build(): List> {
        return serializers
    }
}

private fun  Rpc4kSerializersModuleBuilder.builtinSerializerMethod(
    clazz: KClass,
    typePackage: String,
    typeName: String,
    name: String, provider: (typeArgumentsSerializers: List>) -> KSerializer<*>
) = method(
    clazz,
    serializerName = name,
    serializerPackage = "com.caesarealabs.rpc4k.runtime.implementation.serializers",
    typeName = typeName,
    typePackage = typePackage,
    provider = provider
)


public sealed interface Rpc4kSerializer {

    public val serializerName: KotlinName
    public val provider: ContextualProvider
    public val serializedKClass: KClass

    // KClass is not good enough for type aliases
    public val serializedName: KotlinClassName

    public data class Function(
        override val serializerName: KotlinMethodName,
        override val provider: ContextualProvider,
        override val serializedKClass: KClass,
        override val serializedName: KotlinClassName,
    ) : Rpc4kSerializer

    public data class Object(
        override val serializerName: KotlinClassName,
        override val provider: ContextualProvider.Argless,
        override val serializedKClass: KClass,
        override val serializedName: KotlinClassName,
    ) : Rpc4kSerializer
}

public sealed interface ContextualProvider {
    public class Argless(internal val serializer: KSerializer<*>) : ContextualProvider
    public class WithTypeArguments(internal val provider: (typeArgumentsSerializers: List>) -> KSerializer<*>) : ContextualProvider
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy