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

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

/*
 * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */
@file:Suppress("DEPRECATION_ERROR")
package kotlinx.serialization.internal

import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlin.reflect.*

@InternalSerializationApi
public sealed class AbstractCollectionSerializer : KSerializer {
    protected abstract fun Collection.collectionSize(): Int
    protected abstract fun Collection.collectionIterator(): Iterator
    protected abstract fun builder(): Builder
    protected abstract fun Builder.builderSize(): Int
    protected abstract fun Builder.toResult(): Collection
    protected abstract fun Collection.toBuilder(): Builder
    protected abstract fun Builder.checkCapacity(size: Int)

    abstract override fun serialize(encoder: Encoder, value: Collection)

    @InternalSerializationApi
    public fun merge(decoder: Decoder, previous: Collection?): Collection {
        val builder = previous?.toBuilder() ?: builder()
        val startIndex = builder.builderSize()
        val compositeDecoder = decoder.beginStructure(descriptor)
        if (compositeDecoder.decodeSequentially()) {
            readAll(compositeDecoder, builder, startIndex, readSize(compositeDecoder, builder))
        } else {
            while (true) {
                val index = compositeDecoder.decodeElementIndex(descriptor)
                if (index == CompositeDecoder.DECODE_DONE) break
                readElement(compositeDecoder, startIndex + index, builder)
            }
        }
        compositeDecoder.endStructure(descriptor)
        return builder.toResult()
    }

    override fun deserialize(decoder: Decoder): Collection = merge(decoder, null)

    private fun readSize(decoder: CompositeDecoder, builder: Builder): Int {
        val size = decoder.decodeCollectionSize(descriptor)
        builder.checkCapacity(size)
        return size
    }

    protected abstract fun readElement(decoder: CompositeDecoder, index: Int, builder: Builder, checkIndex: Boolean = true)

    protected abstract fun readAll(decoder: CompositeDecoder, builder: Builder, startIndex: Int, size: Int)
}

@InternalSerializationApi
@Deprecated(level = DeprecationLevel.ERROR, message = "For internal use")
public sealed class ListLikeSerializer(
    private val elementSerializer: KSerializer
) : AbstractCollectionSerializer() {

    protected abstract fun Builder.insert(index: Int, element: Element)
    abstract override val descriptor: SerialDescriptor

    override fun serialize(encoder: Encoder, value: Collection) {
        val size = value.collectionSize()
        val composite = encoder.beginCollection(descriptor, size)
        val iterator = value.collectionIterator()
        for (index in 0 until size)
            composite.encodeSerializableElement(descriptor, index, elementSerializer, iterator.next())
        composite.endStructure(descriptor)
    }

    protected final override fun readAll(decoder: CompositeDecoder, builder: Builder, startIndex: Int, size: Int) {
        require(size >= 0) { "Size must be known in advance when using READ_ALL" }
        for (index in 0 until size)
            readElement(decoder, startIndex + index, builder, checkIndex = false)
    }

    protected override fun readElement(decoder: CompositeDecoder, index: Int, builder: Builder, checkIndex: Boolean) {
        builder.insert(index, decoder.decodeSerializableElement(descriptor, index, elementSerializer))
    }
}

@InternalSerializationApi // Not intended for public use at all
public sealed class MapLikeSerializer>(
    public val keySerializer: KSerializer,
    public val valueSerializer: KSerializer
) : AbstractCollectionSerializer, Collection, Builder>() {

    protected abstract fun Builder.insertKeyValuePair(index: Int, key: Key, value: Value)
    abstract override val descriptor: SerialDescriptor

    protected final override fun readAll(decoder: CompositeDecoder, builder: Builder, startIndex: Int, size: Int) {
        require(size >= 0) { "Size must be known in advance when using READ_ALL" }
        for (index in 0 until size * 2 step 2)
            readElement(decoder, startIndex + index, builder, checkIndex = false)
    }

    final override fun readElement(decoder: CompositeDecoder, index: Int, builder: Builder, checkIndex: Boolean) {
        val key: Key = decoder.decodeSerializableElement(descriptor, index, keySerializer)
        val vIndex = if (checkIndex) {
            decoder.decodeElementIndex(descriptor).also {
                require(it == index + 1) { "Value must follow key in a map, index for key: $index, returned index for value: $it" }
            }
        } else {
            index + 1
        }
        val value: Value = if (builder.containsKey(key) && valueSerializer.descriptor.kind !is PrimitiveKind) {
            decoder.decodeSerializableElement(descriptor, vIndex, valueSerializer, builder.getValue(key))
        } else {
            decoder.decodeSerializableElement(descriptor, vIndex, valueSerializer)
        }
        builder[key] = value
    }

    override fun serialize(encoder: Encoder, value: Collection) {
        val size = value.collectionSize()
        val composite = encoder.beginCollection(descriptor, size)
        val iterator = value.collectionIterator()
        var index = 0
        iterator.forEach { (k, v) ->
            composite.encodeSerializableElement(descriptor, index++, keySerializer, k)
            composite.encodeSerializableElement(descriptor, index++, valueSerializer, v)
        }
        composite.endStructure(descriptor)
    }
}

@InternalSerializationApi
@Deprecated(level = DeprecationLevel.HIDDEN, message = "For internal use")
public abstract class PrimitiveArrayBuilder internal constructor() {
    internal abstract val position: Int
    internal abstract fun ensureCapacity(requiredCapacity: Int = position + 1)
    internal abstract fun build(): Array
}

/**
 * Base serializer for all serializers for primitive arrays.
 *
 * It exists only to avoid code duplication and should not be used or implemented directly.
 * Use concrete serializers ([ByteArraySerializer], etc) instead.
 */
@InternalSerializationApi
@Deprecated(level = DeprecationLevel.HIDDEN, message = "For internal use")
public abstract class PrimitiveArraySerializer> internal constructor(
    primitiveSerializer: KSerializer
) : ListLikeSerializer(primitiveSerializer) {
    final override val descriptor: SerialDescriptor = PrimitiveArrayDescriptor(primitiveSerializer.descriptor)

    final override fun Builder.builderSize(): Int = position
    final override fun Builder.toResult(): Array = build()
    final override fun Builder.checkCapacity(size: Int): Unit = ensureCapacity(size)

    final override fun Array.collectionIterator(): Iterator =
        error("This method lead to boxing and must not be used, use writeContents instead")

    final override fun Builder.insert(index: Int, element: Element): Unit =
        error("This method lead to boxing and must not be used, use Builder.append instead")

    final override fun builder(): Builder = empty().toBuilder()

    protected abstract fun empty(): Array

    protected abstract override fun readElement(
        decoder: CompositeDecoder,
        index: Int,
        builder: Builder,
        checkIndex: Boolean
    )

    protected abstract fun writeContent(encoder: CompositeEncoder, content: Array, size: Int)

    final override fun serialize(encoder: Encoder, value: Array) {
        val size = value.collectionSize()
        val composite = encoder.beginCollection(descriptor, size)
        writeContent(composite, value, size)
        composite.endStructure(descriptor)
    }

    final override fun deserialize(decoder: Decoder): Array = merge(decoder, null)
}

// todo: can be more efficient when array size is know in advance, this one always uses temporary ArrayList as builder
@InternalSerializationApi
@Deprecated(
    message = "Deprecated in the favour of ArraySerializer() factory",
    level = DeprecationLevel.ERROR,
    replaceWith = ReplaceWith("ArraySerializer(eSerializer)", imports = ["kotlinx.serialization.builtins.ArraySerializer"])
)
public class ReferenceArraySerializer(
    private val kClass: KClass,
    eSerializer: KSerializer
) : ListLikeSerializer, ArrayList>(eSerializer) {
    override val descriptor: SerialDescriptor = ArrayClassDesc(eSerializer.descriptor)

    override fun Array.collectionSize(): Int = size
    override fun Array.collectionIterator(): Iterator = iterator()
    override fun builder(): ArrayList = arrayListOf()
    override fun ArrayList.builderSize(): Int = size

    @Suppress("UNCHECKED_CAST")
    override fun ArrayList.toResult(): Array = toNativeArrayImpl(kClass)

    override fun Array.toBuilder(): ArrayList = ArrayList(this.asList())
    override fun ArrayList.checkCapacity(size: Int): Unit = ensureCapacity(size)
    override fun ArrayList.insert(index: Int, element: Element) {
        add(index, element)
    }
}

@InternalSerializationApi
@Deprecated(
    level = DeprecationLevel.ERROR, message = "Use ListSerializer() instead",
    replaceWith = ReplaceWith("ListSerializer(element)", imports = ["kotlinx.serialization.builtins.ListSerializer"])
)
public class ArrayListSerializer(element: KSerializer) : ListLikeSerializer, ArrayList>(element) {
    override val descriptor: SerialDescriptor = ArrayListClassDesc(element.descriptor)
    override fun List.collectionSize(): Int = size
    override fun List.collectionIterator(): Iterator = iterator()
    override fun builder(): ArrayList = arrayListOf()
    override fun ArrayList.builderSize(): Int = size
    override fun ArrayList.toResult(): List = this
    override fun List.toBuilder(): ArrayList = this as? ArrayList ?: ArrayList(this)
    override fun ArrayList.checkCapacity(size: Int): Unit = ensureCapacity(size)
    override fun ArrayList.insert(index: Int, element: E) { add(index, element) }
}

@InternalSerializationApi
@Deprecated(
    level = DeprecationLevel.ERROR, message = "Use SetSerializer() instead",
    replaceWith = ReplaceWith("SetSerializer(eSerializer)", imports = ["kotlinx.serialization.builtins.SetSerializer"])
)
public class LinkedHashSetSerializer(
    eSerializer: KSerializer
) : ListLikeSerializer, LinkedHashSet>(eSerializer) {

    override val descriptor: SerialDescriptor = LinkedHashSetClassDesc(eSerializer.descriptor)
    override fun Set.collectionSize(): Int = size
    override fun Set.collectionIterator(): Iterator = iterator()
    override fun builder(): LinkedHashSet = linkedSetOf()
    override fun LinkedHashSet.builderSize(): Int = size
    override fun LinkedHashSet.toResult(): Set = this
    override fun Set.toBuilder(): LinkedHashSet = this as? LinkedHashSet ?: LinkedHashSet(this)
    override fun LinkedHashSet.checkCapacity(size: Int) {}
    override fun LinkedHashSet.insert(index: Int, element: E) { add(element) }
}

@InternalSerializationApi
@Deprecated(
    level = DeprecationLevel.ERROR, message = "Use SetSerializer() instead",
    replaceWith = ReplaceWith("SetSerializer(eSerializer)", imports = ["kotlinx.serialization.builtins.SetSerializer"])
)
public class HashSetSerializer(
    eSerializer: KSerializer
) : ListLikeSerializer, HashSet>(eSerializer) {

    override val descriptor: SerialDescriptor = HashSetClassDesc(eSerializer.descriptor)
    override fun Set.collectionSize(): Int = size
    override fun Set.collectionIterator(): Iterator = iterator()
    override fun builder(): HashSet = HashSet()
    override fun HashSet.builderSize(): Int = size
    override fun HashSet.toResult(): Set = this
    override fun Set.toBuilder(): HashSet = this as? HashSet ?: HashSet(this)
    override fun HashSet.checkCapacity(size: Int) {}
    override fun HashSet.insert(index: Int, element: E) { add(element) }
}

@InternalSerializationApi
@Deprecated(
    level = DeprecationLevel.ERROR, message = "Use MapSerializer() instead",
    replaceWith = ReplaceWith("MapSerializer(kSerializer, vSerializer)", imports = ["kotlinx.serialization.builtins.MapSerializer"])
)
public class LinkedHashMapSerializer(
    kSerializer: KSerializer, vSerializer: KSerializer
) : MapLikeSerializer, LinkedHashMap>(kSerializer, vSerializer) {

    override val descriptor: SerialDescriptor = LinkedHashMapClassDesc(kSerializer.descriptor, vSerializer.descriptor)
    override fun Map.collectionSize(): Int = size
    override fun Map.collectionIterator(): Iterator> = iterator()
    override fun builder(): LinkedHashMap = LinkedHashMap()
    override fun LinkedHashMap.builderSize(): Int = size
    override fun LinkedHashMap.toResult(): Map = this
    override fun Map.toBuilder(): LinkedHashMap = this as? LinkedHashMap ?: LinkedHashMap(this)
    override fun LinkedHashMap.checkCapacity(size: Int) {}
    override fun LinkedHashMap.insertKeyValuePair(index: Int, key: K, value: V): Unit = set(key, value)
}

@InternalSerializationApi
@Deprecated(
    level = DeprecationLevel.ERROR, message = "Use MapSerializer() instead",
    replaceWith = ReplaceWith("MapSerializer(kSerializer, vSerializer)", imports = ["kotlinx.serialization.builtins.MapSerializer"])
)
public class HashMapSerializer(
    kSerializer: KSerializer, vSerializer: KSerializer
) : MapLikeSerializer, HashMap>(kSerializer, vSerializer) {

    override val descriptor: SerialDescriptor = HashMapClassDesc(kSerializer.descriptor, vSerializer.descriptor)
    override fun Map.collectionSize(): Int = size
    override fun Map.collectionIterator(): Iterator> = iterator()
    override fun builder(): HashMap = HashMap()
    override fun HashMap.builderSize(): Int = size
    override fun HashMap.toResult(): Map = this
    override fun Map.toBuilder(): HashMap = this as? HashMap ?: HashMap(this)
    override fun HashMap.checkCapacity(size: Int) {}
    override fun HashMap.insertKeyValuePair(index: Int, key: K, value: V): Unit = set(key, value)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy