1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
/*
* Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
@file:Suppress("UNCHECKED_CAST")
package kotlinx.serialization.modules
import kotlinx.serialization.KSerializer
import kotlinx.serialization.isInstanceOf
import kotlin.collections.set
import kotlin.reflect.KClass
private typealias SerializersMap = MutableMap<KClass<*>, KSerializer<*>>
/**
* A default implementation of [SerialModule]
* which uses hash maps to store serializers associated with KClasses.
*/
internal class SerialModuleImpl : SerialModule {
private val classMap: SerializersMap = hashMapOf()
private val polyMap: MutableMap<KClass<*>, SerializersMap> = hashMapOf()
private val inverseClassNameMap: MutableMap<KClass<*>, MutableMap<String, KSerializer<*>>> = hashMapOf()
internal fun <T : Any> registerSerializer(
forClass: KClass<T>,
serializer: KSerializer<T>,
allowOverwrite: Boolean = false
) {
if (!allowOverwrite && forClass in classMap) throw SerializerAlreadyRegisteredException(forClass)
classMap[forClass] = serializer
}
internal fun <Base : Any, Sub : Base> registerPolymorphicSerializer(
baseClass: KClass<Base>,
concreteClass: KClass<Sub>,
concreteSerializer: KSerializer<Sub>,
allowOverwrite: Boolean = false
) {
val name = concreteSerializer.descriptor.name
polyMap.getOrPut(baseClass, ::hashMapOf).let { baseClassMap ->
if (!allowOverwrite && concreteClass in baseClassMap) throw SerializerAlreadyRegisteredException(
baseClass,
concreteClass
)
baseClassMap[concreteClass] = concreteSerializer
}
inverseClassNameMap.getOrPut(baseClass, ::hashMapOf)[name] = concreteSerializer
}
override fun <T : Any> getPolymorphic(baseClass: KClass<T>, value: T): KSerializer<out T>? {
if (!value.isInstanceOf(baseClass)) return null
(if (baseClass == Any::class) StandardSubtypesOfAny.getSubclassSerializer(value) else null)?.let { return it as KSerializer<out T> }
return polyMap[baseClass]?.get(value::class) as? KSerializer<out T>
}
override fun <T : Any> getPolymorphic(baseClass: KClass<T>, serializedClassName: String): KSerializer<out T>? {
(if (baseClass == Any::class) StandardSubtypesOfAny.getDefaultDeserializer(
serializedClassName
) else null)?.let { return it as KSerializer<out T> }
return inverseClassNameMap[baseClass]?.get(serializedClassName) as? KSerializer<out T>
}
override fun <T: Any> getContextual(kclass: KClass<T>): KSerializer<T>? = classMap[kclass] as? KSerializer<T>
override fun dumpTo(collector: SerialModuleCollector) {
classMap.forEach { (kclass, serial) ->
collector.contextual(
kclass as KClass<Any>,
serial as KSerializer<Any>
)
}
polyMap.forEach { (baseClass, classMap) ->
classMap.forEach { (actualClass, serializer) ->
collector.polymorphic(
baseClass as KClass<Any>,
actualClass as KClass<Any>,
serializer as KSerializer<Any>
)
}
}
}
}
|