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

commonMain.kotlinx.serialization.internal.Tuples.kt Maven / Gradle / Ivy

There is a newer version: 1.8.0
Show newest version
/*
 * Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */
@file:Suppress("DEPRECATION_ERROR")
@file:OptIn(ExperimentalSerializationApi::class)

package kotlinx.serialization.internal

import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlin.native.concurrent.*

private val NULL = Any()
private const val deprecationMessage =
    "This class is used only by the plugin in generated code and should not be used directly. Use corresponding factory functions instead"

@PublishedApi
internal sealed class KeyValueSerializer(
    protected val keySerializer: KSerializer,
    protected val valueSerializer: KSerializer
) : KSerializer {

    protected abstract val R.key: K
    protected abstract val R.value: V
    protected abstract fun toResult(key: K, value: V): R

    override fun serialize(encoder: Encoder, value: R) {
        val structuredEncoder = encoder.beginStructure(descriptor)
        structuredEncoder.encodeSerializableElement(descriptor, 0, keySerializer, value.key)
        structuredEncoder.encodeSerializableElement(descriptor, 1, valueSerializer, value.value)
        structuredEncoder.endStructure(descriptor)
    }

    override fun deserialize(decoder: Decoder): R = decoder.decodeStructure(descriptor) {
        if (decodeSequentially()) {
            val key = decodeSerializableElement(descriptor, 0, keySerializer)
            val value = decodeSerializableElement(descriptor, 1, valueSerializer)
            return@decodeStructure toResult(key, value)
        }

        var key: Any? = NULL
        var value: Any? = NULL
        mainLoop@ while (true) {
            when (val idx = decodeElementIndex(descriptor)) {
                CompositeDecoder.DECODE_DONE -> {
                    break@mainLoop
                }
                0 -> {
                    key = decodeSerializableElement(descriptor, 0, keySerializer)
                }
                1 -> {
                    value = decodeSerializableElement(descriptor, 1, valueSerializer)
                }
                else -> throw SerializationException("Invalid index: $idx")
            }
        }
        if (key === NULL) throw SerializationException("Element 'key' is missing")
        if (value === NULL) throw SerializationException("Element 'value' is missing")
        @Suppress("UNCHECKED_CAST")
        return@decodeStructure toResult(key as K, value as V)
    }
}

@PublishedApi
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
internal class MapEntrySerializer(
    keySerializer: KSerializer,
    valueSerializer: KSerializer
) : KeyValueSerializer>(keySerializer, valueSerializer) {
    private data class MapEntry(override val key: K, override val value: V) : Map.Entry

    /*
     * Kind 'MAP' because it is represented in a map-like manner with "key: value" serialized directly
     */
    override val descriptor: SerialDescriptor = buildSerialDescriptor("kotlin.collections.Map.Entry", StructureKind.MAP) {
        element("key", keySerializer.descriptor)
        element("value", valueSerializer.descriptor)
    }

    override val Map.Entry.key: K get() = this.key
    override val Map.Entry.value: V get() = this.value
    override fun toResult(key: K, value: V): Map.Entry = MapEntry(key, value)
}

@PublishedApi
internal class PairSerializer(
    keySerializer: KSerializer,
    valueSerializer: KSerializer
) : KeyValueSerializer>(keySerializer, valueSerializer) {
    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("kotlin.Pair") {
        element("first", keySerializer.descriptor)
        element("second", valueSerializer.descriptor)
    }
    override val Pair.key: K get() = this.first
    override val Pair.value: V get() = this.second

    override fun toResult(key: K, value: V): Pair = key to value
}


@PublishedApi
internal class TripleSerializer(
    private val aSerializer: KSerializer,
    private val bSerializer: KSerializer,
    private val cSerializer: KSerializer
) : KSerializer> {

    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("kotlin.Triple") {
        element("first", aSerializer.descriptor)
        element("second", bSerializer.descriptor)
        element("third", cSerializer.descriptor)
    }

    override fun serialize(encoder: Encoder, value: Triple) {
        val structuredEncoder = encoder.beginStructure(descriptor)
        structuredEncoder.encodeSerializableElement(descriptor, 0, aSerializer, value.first)
        structuredEncoder.encodeSerializableElement(descriptor, 1, bSerializer, value.second)
        structuredEncoder.encodeSerializableElement(descriptor, 2, cSerializer, value.third)
        structuredEncoder.endStructure(descriptor)
    }

    override fun deserialize(decoder: Decoder): Triple {
        val composite = decoder.beginStructure(descriptor)
        if (composite.decodeSequentially()) {
            return decodeSequentially(composite)
        }
        return decodeStructure(composite)
    }

    private fun decodeSequentially(composite: CompositeDecoder): Triple {
        val a = composite.decodeSerializableElement(descriptor, 0, aSerializer)
        val b = composite.decodeSerializableElement(descriptor, 1, bSerializer)
        val c = composite.decodeSerializableElement(descriptor, 2, cSerializer)
        composite.endStructure(descriptor)
        return Triple(a, b, c)
    }

    private fun decodeStructure(composite: CompositeDecoder): Triple {
        var a: Any? = NULL
        var b: Any? = NULL
        var c: Any? = NULL
        mainLoop@ while (true) {
            when (val index = composite.decodeElementIndex(descriptor)) {
                CompositeDecoder.DECODE_DONE -> {
                    break@mainLoop
                }
                0 -> {
                    a = composite.decodeSerializableElement(descriptor, 0, aSerializer)
                }
                1 -> {
                    b = composite.decodeSerializableElement(descriptor, 1, bSerializer)
                }
                2 -> {
                    c = composite.decodeSerializableElement(descriptor, 2, cSerializer)
                }
                else -> throw SerializationException("Unexpected index $index")
            }
        }
        composite.endStructure(descriptor)
        if (a === NULL) throw SerializationException("Element 'first' is missing")
        if (b === NULL) throw SerializationException("Element 'second' is missing")
        if (c === NULL) throw SerializationException("Element 'third' is missing")
        @Suppress("UNCHECKED_CAST")
        return Triple(a as A, b as B, c as C)
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy