1 /*
<lambda>null2  * Copyright 2017-2020 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 package kotlinx.serialization.internal
7 
8 import kotlinx.serialization.*
9 import kotlinx.serialization.descriptors.*
10 import kotlinx.serialization.encoding.*
11 import kotlin.reflect.*
12 
13 @InternalSerializationApi
14 public sealed class AbstractCollectionSerializer<Element, Collection, Builder> : KSerializer<Collection> {
15     protected abstract fun Collection.collectionSize(): Int
16     protected abstract fun Collection.collectionIterator(): Iterator<Element>
17     protected abstract fun builder(): Builder
18     protected abstract fun Builder.builderSize(): Int
19     protected abstract fun Builder.toResult(): Collection
20     protected abstract fun Collection.toBuilder(): Builder
21     protected abstract fun Builder.checkCapacity(size: Int)
22 
23     abstract override fun serialize(encoder: Encoder, value: Collection)
24 
25     @InternalSerializationApi
26     public fun merge(decoder: Decoder, previous: Collection?): Collection {
27         val builder = previous?.toBuilder() ?: builder()
28         val startIndex = builder.builderSize()
29         val compositeDecoder = decoder.beginStructure(descriptor)
30         if (compositeDecoder.decodeSequentially()) {
31             readAll(compositeDecoder, builder, startIndex, readSize(compositeDecoder, builder))
32         } else {
33             while (true) {
34                 val index = compositeDecoder.decodeElementIndex(descriptor)
35                 if (index == CompositeDecoder.DECODE_DONE) break
36                 readElement(compositeDecoder, startIndex + index, builder)
37             }
38         }
39         compositeDecoder.endStructure(descriptor)
40         return builder.toResult()
41     }
42 
43     override fun deserialize(decoder: Decoder): Collection = merge(decoder, null)
44 
45     private fun readSize(decoder: CompositeDecoder, builder: Builder): Int {
46         val size = decoder.decodeCollectionSize(descriptor)
47         builder.checkCapacity(size)
48         return size
49     }
50 
51     protected abstract fun readElement(decoder: CompositeDecoder, index: Int, builder: Builder, checkIndex: Boolean = true)
52 
53     protected abstract fun readAll(decoder: CompositeDecoder, builder: Builder, startIndex: Int, size: Int)
54 }
55 
56 @PublishedApi
57 internal sealed class CollectionLikeSerializer<Element, Collection, Builder>(
58     private val elementSerializer: KSerializer<Element>
59 ) : AbstractCollectionSerializer<Element, Collection, Builder>() {
60 
Buildernull61     protected abstract fun Builder.insert(index: Int, element: Element)
62     abstract override val descriptor: SerialDescriptor
63 
64     override fun serialize(encoder: Encoder, value: Collection) {
65         val size = value.collectionSize()
66         encoder.encodeCollection(descriptor, size) {
67             val iterator = value.collectionIterator()
68             for (index in 0 until size)
69                 encodeSerializableElement(descriptor, index, elementSerializer, iterator.next())
70         }
71     }
72 
readAllnull73     final override fun readAll(decoder: CompositeDecoder, builder: Builder, startIndex: Int, size: Int) {
74         require(size >= 0) { "Size must be known in advance when using READ_ALL" }
75         for (index in 0 until size)
76             readElement(decoder, startIndex + index, builder, checkIndex = false)
77     }
78 
readElementnull79     override fun readElement(decoder: CompositeDecoder, index: Int, builder: Builder, checkIndex: Boolean) {
80         builder.insert(index, decoder.decodeSerializableElement(descriptor, index, elementSerializer))
81     }
82 }
83 
84 @InternalSerializationApi // TODO tech debt: it's used in ProtoBuf
85 public sealed class MapLikeSerializer<Key, Value, Collection, Builder : MutableMap<Key, Value>>(
86     public val keySerializer: KSerializer<Key>,
87     public val valueSerializer: KSerializer<Value>
88 ) : AbstractCollectionSerializer<Map.Entry<Key, Value>, Collection, Builder>() {
89 
insertKeyValuePairnull90     protected abstract fun Builder.insertKeyValuePair(index: Int, key: Key, value: Value)
91     abstract override val descriptor: SerialDescriptor
92 
93     protected final override fun readAll(decoder: CompositeDecoder, builder: Builder, startIndex: Int, size: Int) {
94         require(size >= 0) { "Size must be known in advance when using READ_ALL" }
95         for (index in 0 until size * 2 step 2)
96             readElement(decoder, startIndex + index, builder, checkIndex = false)
97     }
98 
readElementnull99     final override fun readElement(decoder: CompositeDecoder, index: Int, builder: Builder, checkIndex: Boolean) {
100         val key: Key = decoder.decodeSerializableElement(descriptor, index, keySerializer)
101         val vIndex = if (checkIndex) {
102             decoder.decodeElementIndex(descriptor).also {
103                 require(it == index + 1) { "Value must follow key in a map, index for key: $index, returned index for value: $it" }
104             }
105         } else {
106             index + 1
107         }
108         val value: Value = if (builder.containsKey(key) && valueSerializer.descriptor.kind !is PrimitiveKind) {
109             decoder.decodeSerializableElement(descriptor, vIndex, valueSerializer, builder.getValue(key))
110         } else {
111             decoder.decodeSerializableElement(descriptor, vIndex, valueSerializer)
112         }
113         builder[key] = value
114     }
115 
serializenull116     override fun serialize(encoder: Encoder, value: Collection) {
117         val size = value.collectionSize()
118         encoder.encodeCollection(descriptor, size) {
119             val iterator = value.collectionIterator()
120             var index = 0
121             iterator.forEach { (k, v) ->
122                 encodeSerializableElement(descriptor, index++, keySerializer, k)
123                 encodeSerializableElement(descriptor, index++, valueSerializer, v)
124             }
125         }
126     }
127 }
128 
129 @PublishedApi
130 internal abstract class PrimitiveArrayBuilder<Array> internal constructor() {
131     internal abstract val position: Int
ensureCapacitynull132     internal abstract fun ensureCapacity(requiredCapacity: Int = position + 1)
133     internal abstract fun build(): Array
134 }
135 
136 /**
137  * Base serializer for all serializers for primitive arrays.
138  *
139  * It exists only to avoid code duplication and should not be used or implemented directly.
140  * Use concrete serializers ([ByteArraySerializer], etc) instead.
141  */
142 @PublishedApi
143 internal abstract class PrimitiveArraySerializer<Element, Array, Builder
144 : PrimitiveArrayBuilder<Array>> internal constructor(
145     primitiveSerializer: KSerializer<Element>
146 ) : CollectionLikeSerializer<Element, Array, Builder>(primitiveSerializer) {
147     final override val descriptor: SerialDescriptor = PrimitiveArrayDescriptor(primitiveSerializer.descriptor)
148 
149     final override fun Builder.builderSize(): Int = position
150     final override fun Builder.toResult(): Array = build()
151     final override fun Builder.checkCapacity(size: Int): Unit = ensureCapacity(size)
152 
153     final override fun Array.collectionIterator(): Iterator<Element> =
154         error("This method lead to boxing and must not be used, use writeContents instead")
155 
156     final override fun Builder.insert(index: Int, element: Element): Unit =
157         error("This method lead to boxing and must not be used, use Builder.append instead")
158 
159     final override fun builder(): Builder = empty().toBuilder()
160 
161     protected abstract fun empty(): Array
162 
163     abstract override fun readElement(
164         decoder: CompositeDecoder,
165         index: Int,
166         builder: Builder,
167         checkIndex: Boolean
168     )
169 
170     protected abstract fun writeContent(encoder: CompositeEncoder, content: Array, size: Int)
171 
172     final override fun serialize(encoder: Encoder, value: Array) {
173         val size = value.collectionSize()
174         encoder.encodeCollection(descriptor, size) {
175             writeContent(this, value, size)
176         }
177     }
178 
179     final override fun deserialize(decoder: Decoder): Array = merge(decoder, null)
180 }
181 
182 // todo: can be more efficient when array size is know in advance, this one always uses temporary ArrayList as builder
183 @PublishedApi
184 internal class ReferenceArraySerializer<ElementKlass : Any, Element : ElementKlass?>(
185     private val kClass: KClass<ElementKlass>,
186     eSerializer: KSerializer<Element>
187 ) : CollectionLikeSerializer<Element, Array<Element>, ArrayList<Element>>(eSerializer) {
188     override val descriptor: SerialDescriptor = ArrayClassDesc(eSerializer.descriptor)
189 
collectionSizenull190     override fun Array<Element>.collectionSize(): Int = size
191     override fun Array<Element>.collectionIterator(): Iterator<Element> = iterator()
192     override fun builder(): ArrayList<Element> = arrayListOf()
193     override fun ArrayList<Element>.builderSize(): Int = size
194 
195     @Suppress("UNCHECKED_CAST")
196     override fun ArrayList<Element>.toResult(): Array<Element> = toNativeArrayImpl<ElementKlass, Element>(kClass)
197 
198     override fun Array<Element>.toBuilder(): ArrayList<Element> = ArrayList(this.asList())
199     override fun ArrayList<Element>.checkCapacity(size: Int): Unit = ensureCapacity(size)
200     override fun ArrayList<Element>.insert(index: Int, element: Element) {
201         add(index, element)
202     }
203 }
204 
205 @PublishedApi
206 internal abstract class CollectionSerializer<E, C: Collection<E>, B>(element: KSerializer<E>) : CollectionLikeSerializer<E, C, B>(element) {
collectionSizenull207     override fun C.collectionSize(): Int = size
208     override fun C.collectionIterator(): Iterator<E> = iterator()
209 }
210 
211 @InternalSerializationApi
212 @PublishedApi
213 internal class ArrayListSerializer<E>(element: KSerializer<E>) : CollectionSerializer<E, List<E>, ArrayList<E>>(element) {
214     override val descriptor: SerialDescriptor = ArrayListClassDesc(element.descriptor)
215 
216     override fun builder(): ArrayList<E> = arrayListOf()
217     override fun ArrayList<E>.builderSize(): Int = size
218     override fun ArrayList<E>.toResult(): List<E> = this
219     override fun List<E>.toBuilder(): ArrayList<E> = this as? ArrayList<E> ?: ArrayList(this)
220     override fun ArrayList<E>.checkCapacity(size: Int): Unit = ensureCapacity(size)
221     override fun ArrayList<E>.insert(index: Int, element: E) { add(index, element) }
222 }
223 
224 @PublishedApi
225 internal class LinkedHashSetSerializer<E>(
226     eSerializer: KSerializer<E>
227 ) : CollectionSerializer<E, Set<E>, LinkedHashSet<E>>(eSerializer) {
228     override val descriptor: SerialDescriptor = LinkedHashSetClassDesc(eSerializer.descriptor)
229 
buildernull230     override fun builder(): LinkedHashSet<E> = linkedSetOf()
231     override fun LinkedHashSet<E>.builderSize(): Int = size
232     override fun LinkedHashSet<E>.toResult(): Set<E> = this
233     override fun Set<E>.toBuilder(): LinkedHashSet<E> = this as? LinkedHashSet<E> ?: LinkedHashSet(this)
234     override fun LinkedHashSet<E>.checkCapacity(size: Int) {}
insertnull235     override fun LinkedHashSet<E>.insert(index: Int, element: E) { add(element) }
236 }
237 
238 @PublishedApi
239 internal class HashSetSerializer<E>(
240     eSerializer: KSerializer<E>
241 ) : CollectionSerializer<E, Set<E>, HashSet<E>>(eSerializer) {
242     override val descriptor: SerialDescriptor = HashSetClassDesc(eSerializer.descriptor)
243 
buildernull244     override fun builder(): HashSet<E> = HashSet()
245     override fun HashSet<E>.builderSize(): Int = size
246     override fun HashSet<E>.toResult(): Set<E> = this
247     override fun Set<E>.toBuilder(): HashSet<E> = this as? HashSet<E> ?: HashSet(this)
248     override fun HashSet<E>.checkCapacity(size: Int) {}
insertnull249     override fun HashSet<E>.insert(index: Int, element: E) { add(element) }
250 }
251 
252 @PublishedApi
253 internal class LinkedHashMapSerializer<K, V>(
254     kSerializer: KSerializer<K>, vSerializer: KSerializer<V>
255 ) : MapLikeSerializer<K, V, Map<K, V>, LinkedHashMap<K, V>>(kSerializer, vSerializer) {
256 
257     override val descriptor: SerialDescriptor = LinkedHashMapClassDesc(kSerializer.descriptor, vSerializer.descriptor)
collectionSizenull258     override fun Map<K, V>.collectionSize(): Int = size
259     override fun Map<K, V>.collectionIterator(): Iterator<Map.Entry<K, V>> = iterator()
260     override fun builder(): LinkedHashMap<K, V> = LinkedHashMap()
261     override fun LinkedHashMap<K, V>.builderSize(): Int = size * 2
262     override fun LinkedHashMap<K, V>.toResult(): Map<K, V> = this
263     override fun Map<K, V>.toBuilder(): LinkedHashMap<K, V> = this as? LinkedHashMap<K, V> ?: LinkedHashMap(this)
264     override fun LinkedHashMap<K, V>.checkCapacity(size: Int) {}
insertKeyValuePairnull265     override fun LinkedHashMap<K, V>.insertKeyValuePair(index: Int, key: K, value: V): Unit = set(key, value)
266 }
267 
268 @PublishedApi
269 internal class HashMapSerializer<K, V>(
270     kSerializer: KSerializer<K>, vSerializer: KSerializer<V>
271 ) : MapLikeSerializer<K, V, Map<K, V>, HashMap<K, V>>(kSerializer, vSerializer) {
272 
273     override val descriptor: SerialDescriptor = HashMapClassDesc(kSerializer.descriptor, vSerializer.descriptor)
274     override fun Map<K, V>.collectionSize(): Int = size
275     override fun Map<K, V>.collectionIterator(): Iterator<Map.Entry<K, V>> = iterator()
276     override fun builder(): HashMap<K, V> = HashMap()
277     override fun HashMap<K, V>.builderSize(): Int = size * 2
278     override fun HashMap<K, V>.toResult(): Map<K, V> = this
279     override fun Map<K, V>.toBuilder(): HashMap<K, V> = this as? HashMap<K, V> ?: HashMap(this)
280     override fun HashMap<K, V>.checkCapacity(size: Int) {}
281     override fun HashMap<K, V>.insertKeyValuePair(index: Int, key: K, value: V): Unit = set(key, value)
282 }
283