1 /* 2 * Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. 3 */ 4 @file:Suppress("DEPRECATION_ERROR") 5 @file:OptIn(ExperimentalSerializationApi::class) 6 7 package kotlinx.serialization.internal 8 9 import kotlinx.serialization.* 10 import kotlinx.serialization.descriptors.* 11 import kotlinx.serialization.encoding.* 12 import kotlin.native.concurrent.* 13 14 private val NULL = Any() 15 private const val deprecationMessage = 16 "This class is used only by the plugin in generated code and should not be used directly. Use corresponding factory functions instead" 17 18 @PublishedApi 19 internal sealed class KeyValueSerializer<K, V, R>( 20 protected val keySerializer: KSerializer<K>, 21 protected val valueSerializer: KSerializer<V> 22 ) : KSerializer<R> { 23 24 protected abstract val R.key: K 25 protected abstract val R.value: V toResultnull26 protected abstract fun toResult(key: K, value: V): R 27 28 override fun serialize(encoder: Encoder, value: R) { 29 val structuredEncoder = encoder.beginStructure(descriptor) 30 structuredEncoder.encodeSerializableElement(descriptor, 0, keySerializer, value.key) 31 structuredEncoder.encodeSerializableElement(descriptor, 1, valueSerializer, value.value) 32 structuredEncoder.endStructure(descriptor) 33 } 34 <lambda>null35 override fun deserialize(decoder: Decoder): R = decoder.decodeStructure(descriptor) { 36 if (decodeSequentially()) { 37 val key = decodeSerializableElement(descriptor, 0, keySerializer) 38 val value = decodeSerializableElement(descriptor, 1, valueSerializer) 39 return@decodeStructure toResult(key, value) 40 } 41 42 var key: Any? = NULL 43 var value: Any? = NULL 44 mainLoop@ while (true) { 45 when (val idx = decodeElementIndex(descriptor)) { 46 CompositeDecoder.DECODE_DONE -> { 47 break@mainLoop 48 } 49 0 -> { 50 key = decodeSerializableElement(descriptor, 0, keySerializer) 51 } 52 1 -> { 53 value = decodeSerializableElement(descriptor, 1, valueSerializer) 54 } 55 else -> throw SerializationException("Invalid index: $idx") 56 } 57 } 58 if (key === NULL) throw SerializationException("Element 'key' is missing") 59 if (value === NULL) throw SerializationException("Element 'value' is missing") 60 @Suppress("UNCHECKED_CAST") 61 return@decodeStructure toResult(key as K, value as V) 62 } 63 } 64 65 @PublishedApi 66 @Suppress("EXTENSION_SHADOWED_BY_MEMBER") 67 internal class MapEntrySerializer<K, V>( 68 keySerializer: KSerializer<K>, 69 valueSerializer: KSerializer<V> 70 ) : KeyValueSerializer<K, V, Map.Entry<K, V>>(keySerializer, valueSerializer) { 71 private data class MapEntry<K, V>(override val key: K, override val value: V) : Map.Entry<K, V> 72 73 /* 74 * Kind 'MAP' because it is represented in a map-like manner with "key: value" serialized directly 75 */ <lambda>null76 override val descriptor: SerialDescriptor = buildSerialDescriptor("kotlin.collections.Map.Entry", StructureKind.MAP) { 77 element("key", keySerializer.descriptor) 78 element("value", valueSerializer.descriptor) 79 } 80 81 override val Map.Entry<K, V>.key: K get() = this.key 82 override val Map.Entry<K, V>.value: V get() = this.value toResultnull83 override fun toResult(key: K, value: V): Map.Entry<K, V> = MapEntry(key, value) 84 } 85 86 @PublishedApi 87 internal class PairSerializer<K, V>( 88 keySerializer: KSerializer<K>, 89 valueSerializer: KSerializer<V> 90 ) : KeyValueSerializer<K, V, Pair<K, V>>(keySerializer, valueSerializer) { 91 override val descriptor: SerialDescriptor = buildClassSerialDescriptor("kotlin.Pair") { 92 element("first", keySerializer.descriptor) 93 element("second", valueSerializer.descriptor) 94 } 95 override val Pair<K, V>.key: K get() = this.first 96 override val Pair<K, V>.value: V get() = this.second 97 98 override fun toResult(key: K, value: V): Pair<K, V> = key to value 99 } 100 101 102 @PublishedApi 103 internal class TripleSerializer<A, B, C>( 104 private val aSerializer: KSerializer<A>, 105 private val bSerializer: KSerializer<B>, 106 private val cSerializer: KSerializer<C> 107 ) : KSerializer<Triple<A, B, C>> { 108 <lambda>null109 override val descriptor: SerialDescriptor = buildClassSerialDescriptor("kotlin.Triple") { 110 element("first", aSerializer.descriptor) 111 element("second", bSerializer.descriptor) 112 element("third", cSerializer.descriptor) 113 } 114 serializenull115 override fun serialize(encoder: Encoder, value: Triple<A, B, C>) { 116 val structuredEncoder = encoder.beginStructure(descriptor) 117 structuredEncoder.encodeSerializableElement(descriptor, 0, aSerializer, value.first) 118 structuredEncoder.encodeSerializableElement(descriptor, 1, bSerializer, value.second) 119 structuredEncoder.encodeSerializableElement(descriptor, 2, cSerializer, value.third) 120 structuredEncoder.endStructure(descriptor) 121 } 122 deserializenull123 override fun deserialize(decoder: Decoder): Triple<A, B, C> { 124 val composite = decoder.beginStructure(descriptor) 125 if (composite.decodeSequentially()) { 126 return decodeSequentially(composite) 127 } 128 return decodeStructure(composite) 129 } 130 decodeSequentiallynull131 private fun decodeSequentially(composite: CompositeDecoder): Triple<A, B, C> { 132 val a = composite.decodeSerializableElement(descriptor, 0, aSerializer) 133 val b = composite.decodeSerializableElement(descriptor, 1, bSerializer) 134 val c = composite.decodeSerializableElement(descriptor, 2, cSerializer) 135 composite.endStructure(descriptor) 136 return Triple(a, b, c) 137 } 138 decodeStructurenull139 private fun decodeStructure(composite: CompositeDecoder): Triple<A, B, C> { 140 var a: Any? = NULL 141 var b: Any? = NULL 142 var c: Any? = NULL 143 mainLoop@ while (true) { 144 when (val index = composite.decodeElementIndex(descriptor)) { 145 CompositeDecoder.DECODE_DONE -> { 146 break@mainLoop 147 } 148 0 -> { 149 a = composite.decodeSerializableElement(descriptor, 0, aSerializer) 150 } 151 1 -> { 152 b = composite.decodeSerializableElement(descriptor, 1, bSerializer) 153 } 154 2 -> { 155 c = composite.decodeSerializableElement(descriptor, 2, cSerializer) 156 } 157 else -> throw SerializationException("Unexpected index $index") 158 } 159 } 160 composite.endStructure(descriptor) 161 if (a === NULL) throw SerializationException("Element 'first' is missing") 162 if (b === NULL) throw SerializationException("Element 'second' is missing") 163 if (c === NULL) throw SerializationException("Element 'third' is missing") 164 @Suppress("UNCHECKED_CAST") 165 return Triple(a as A, b as B, c as C) 166 } 167 } 168