• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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