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

jvmMain.serialize.binary.reflect.ReflectionBinarySerializer.kt Maven / Gradle / Ivy

There is a newer version: 12.0.0
Show newest version
package ch.softappeal.yass2.serialize.binary.reflect

import ch.softappeal.yass2.serialize.binary.*
import kotlin.reflect.*
import kotlin.reflect.full.*

public fun KClass<*>.metaClass(baseEncoderTypes: List>): MetaClass {
    require(!java.isEnum) { "type '$this' is enum" }
    require(!isAbstract) { "type '$this' is abstract" }
    return MetaClass(
        this,
        memberProperties
            .filter { !isSubclassOf(Throwable::class) || (it.name != "cause" && it.name != "message") }
            .sortedBy { it.name }
            .map { property ->
                (property.returnType.classifier as KClass<*>).metaProperty(
                    @Suppress("UNCHECKED_CAST") (property as KProperty1),
                    baseEncoderTypes,
                    property.returnType.isMarkedNullable,
                )
            },
        (primaryConstructor ?: error("'$this' has no primary constructor")).valueParameters.map { it.name!! }
    )
}

public fun reflectionBinarySerializer(
    baseEncoders: List>,
    treeConcreteClasses: List> = emptyList(),
    graphConcreteClasses: List> = emptyList(),
): BinarySerializer {
    val baseEncoderTypes = baseEncoders.map { it.type }
    val encoders = mutableListOf()
    encoders.addAll(baseEncoders)
    fun List>.add(graph: Boolean) = forEach { klass ->
        val metaClass = klass.metaClass(baseEncoderTypes)
        encoders.add(ClassEncoder(
            @Suppress("UNCHECKED_CAST") (klass as KClass),
            graph,
            { writer, instance ->
                metaClass.properties.forEach { it.write(writer, it.property.get(instance)) }
            },
            { reader ->
                val parameterProperties = Array(metaClass.parameterProperties.size) { metaClass.parameterProperties[it].read(reader) }
                val created = klass.primaryConstructor!!.call(*parameterProperties)
                val instance = if (graph) reader.created(created) else created
                metaClass.bodyProperties.forEach { it.mutableProperty().set(instance, it.read(reader)) }
                instance
            },
        ))
    }
    treeConcreteClasses.add(false)
    graphConcreteClasses.add(true)
    return BinarySerializer(encoders)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy