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

serialize.fast.FastSerializers.kt Maven / Gradle / Ivy

There is a newer version: 66.0.0
Show newest version
package ch.softappeal.yass.serialize.fast

import ch.softappeal.yass.Tag
import ch.softappeal.yass.allFields
import ch.softappeal.yass.tag
import java.io.PrintWriter
import java.lang.reflect.Field

/** This serializer assigns type and field id's automatically. Therefore, all peers must have the same version of the contract! */
@JvmOverloads
fun simpleFastSerializer(
    baseTypeSerializers: List>, treeConcreteClasses: List>, graphConcreteClasses: List> = emptyList()
) = object : FastSerializer() {
    init {
        var id = FirstTypeId
        for (typeSerializer in baseTypeSerializers) addBaseType(TypeDesc(id++, typeSerializer))
        for (type in treeConcreteClasses) if (type.isEnum) addEnum(id++, type) else addClass(id++, type, false)
        for (type in graphConcreteClasses) {
            checkClass(type)
            addClass(id++, type, true)
        }
        fixupFields()
    }

    fun addClass(typeId: Int, type: Class<*>, graph: Boolean) {
        val id2field = mutableMapOf()
        var fieldId = FirstFieldId
        for (field in allFields(type)) id2field[fieldId++] = field
        addClass(typeId, type, graph, id2field)
    }
}

/** This serializer assigns type and field id's from its [Tag]. */
@JvmOverloads
fun taggedFastSerializer(
    baseTypeDescs: Collection, treeConcreteClasses: Collection>, graphConcreteClasses: Collection> = emptyList()
) = object : FastSerializer() {
    init {
        baseTypeDescs.forEach { addBaseType(it) }
        treeConcreteClasses.forEach { type -> if (type.isEnum) addEnum(tag(type), type) else addClass(type, false) }
        graphConcreteClasses.forEach { type ->
            checkClass(type)
            addClass(type, true)
        }
        fixupFields()
    }

    fun addClass(type: Class<*>, graph: Boolean) {
        val id2field = mutableMapOf()
        for (field in allFields(type)) {
            val id = tag(field)
            val oldField = id2field.put(id, field)
            require(oldField == null) { "tag $id used for fields '$field' and '$oldField'" }
        }
        addClass(tag(type), type, graph, id2field)
    }
}

fun FastSerializer.print(printer: PrintWriter) = id2typeSerializer.forEach { id, typeSerializer ->
    if (id < FirstTypeId) return@forEach
    val type = typeSerializer.type
    printer.print("$id: ${type.canonicalName}")
    if (typeSerializer is BaseTypeSerializer<*>) {
        printer.println()
        if (type.isEnum) for ((i, c) in type.enumConstants.withIndex()) printer.println("    $i: $c")
    } else if (typeSerializer is ClassTypeSerializer) {
        printer.println(" (graph=${typeSerializer.graph})")
        for (fd in typeSerializer.fieldDescs) printer.println("    ${fd.id}: ${fd.serializer.field.toGenericString()}")
    }
    printer.println()
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy