diff options
author | Vsevolod Tolstopyatov <qwwdfsad@gmail.com> | 2020-09-14 04:04:34 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-14 14:04:34 +0300 |
commit | 0e4e0e729f97df1844a266647c2c4786ed780b2f (patch) | |
tree | acc8e0a73c01bf223c5b92b4200e963355e0558d /core/commonMain/src/kotlinx/serialization/internal/Tuples.kt | |
parent | 1df4d619058cd8774cf3b895bde660d15483d935 (diff) | |
download | kotlinx.serialization-0e4e0e729f97df1844a266647c2c4786ed780b2f.tar.gz |
Extract JSON to a separate dependency, rename 'runtime' to 'core' (#1062)
* Introduce JsonInternalDependencies
* Make SealedClassSerializer public
* Duplicate test code in a few places
Fixes #994
Diffstat (limited to 'core/commonMain/src/kotlinx/serialization/internal/Tuples.kt')
-rw-r--r-- | core/commonMain/src/kotlinx/serialization/internal/Tuples.kt | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/core/commonMain/src/kotlinx/serialization/internal/Tuples.kt b/core/commonMain/src/kotlinx/serialization/internal/Tuples.kt new file mode 100644 index 00000000..8bd4deb2 --- /dev/null +++ b/core/commonMain/src/kotlinx/serialization/internal/Tuples.kt @@ -0,0 +1,191 @@ +/* + * Copyright 2017-2020 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.* + +@SharedImmutable +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" + +@InternalSerializationApi +@Deprecated(message = deprecationMessage, level = DeprecationLevel.HIDDEN) +public sealed class KeyValueSerializer<K, V, R>( + protected val keySerializer: KSerializer<K>, + protected val valueSerializer: KSerializer<V> +) : KSerializer<R> { + + 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 { + val composite = decoder.beginStructure(descriptor) + if (composite.decodeSequentially()) { + val key = composite.decodeSerializableElement(descriptor, 0, keySerializer) + val value = composite.decodeSerializableElement(descriptor, 1, valueSerializer) + return toResult(key, value) + } + + var key: Any? = NULL + var value: Any? = NULL + mainLoop@ while (true) { + when (val idx = composite.decodeElementIndex(descriptor)) { + CompositeDecoder.DECODE_DONE -> { + break@mainLoop + } + 0 -> { + key = composite.decodeSerializableElement(descriptor, 0, keySerializer) + } + 1 -> { + value = composite.decodeSerializableElement(descriptor, 1, valueSerializer) + } + else -> throw SerializationException("Invalid index: $idx") + } + } + composite.endStructure(descriptor) + if (key === NULL) throw SerializationException("Element 'key' is missing") + if (value === NULL) throw SerializationException("Element 'value' is missing") + @Suppress("UNCHECKED_CAST") + return toResult(key as K, value as V) + } +} + +@InternalSerializationApi +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +@Deprecated( + message = deprecationMessage, level = DeprecationLevel.HIDDEN, replaceWith = ReplaceWith( + "MapEntrySerializer(keySerializer, valueSerializer, cSerializer)", + imports = ["kotlinx.serialization.builtins.MapEntrySerializer"] + ) +) +public class MapEntrySerializer<K, V>( + keySerializer: KSerializer<K>, + valueSerializer: KSerializer<V> +) : KeyValueSerializer<K, V, Map.Entry<K, V>>(keySerializer, valueSerializer) { + private data class MapEntry<K, V>(override val key: K, override val value: V) : Map.Entry<K, V> + + /* + * 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<K, V>.key: K get() = this.key + override val Map.Entry<K, V>.value: V get() = this.value + override fun toResult(key: K, value: V): Map.Entry<K, V> = MapEntry(key, value) +} + +@InternalSerializationApi +@Deprecated( + message = deprecationMessage, level = DeprecationLevel.HIDDEN, replaceWith = ReplaceWith( + "PairSerializer(keySerializer, valueSerializer, cSerializer)", + imports = ["kotlinx.serialization.builtins.PairSerializer"] + ) +) +public class PairSerializer<K, V>( + keySerializer: KSerializer<K>, + valueSerializer: KSerializer<V> +) : KeyValueSerializer<K, V, Pair<K, V>>(keySerializer, valueSerializer) { + override val descriptor: SerialDescriptor = buildClassSerialDescriptor("kotlin.Pair") { + element("first", keySerializer.descriptor) + element("second", valueSerializer.descriptor) + } + override val Pair<K, V>.key: K get() = this.first + override val Pair<K, V>.value: V get() = this.second + + override fun toResult(key: K, value: V): Pair<K, V> = key to value +} + + +@InternalSerializationApi +@Deprecated( + message = deprecationMessage, + level = DeprecationLevel.HIDDEN, + replaceWith = ReplaceWith( + "TripleSerializer(aSerializer, bSerializer, cSerializer)", + imports = ["kotlinx.serialization.builtins.TripleSerializer"] + ) +) +public class TripleSerializer<A, B, C>( + private val aSerializer: KSerializer<A>, + private val bSerializer: KSerializer<B>, + private val cSerializer: KSerializer<C> +) : KSerializer<Triple<A, B, C>> { + + 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<A, B, C>) { + 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<A, B, C> { + val composite = decoder.beginStructure(descriptor) + if (composite.decodeSequentially()) { + return decodeSequentially(composite) + } + return decodeStructure(composite) + } + + private fun decodeSequentially(composite: CompositeDecoder): Triple<A, B, C> { + 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<A, B, C> { + 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) + } +} |