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:OptIn(ExperimentalSerializationApi::class)
5
6 package kotlinx.serialization.json.internal
7
8 import kotlinx.serialization.*
9 import kotlinx.serialization.descriptors.*
10 import kotlinx.serialization.json.*
11 import kotlinx.serialization.modules.*
12 import kotlin.jvm.*
13
14 internal enum class WriteMode(@JvmField val begin: Char, @JvmField val end: Char) {
15 OBJ(BEGIN_OBJ, END_OBJ),
16 LIST(BEGIN_LIST, END_LIST),
17 MAP(BEGIN_OBJ, END_OBJ),
18 POLY_OBJ(BEGIN_LIST, END_LIST);
19 }
20
21 @OptIn(ExperimentalSerializationApi::class)
switchModenull22 internal fun Json.switchMode(desc: SerialDescriptor): WriteMode =
23 when (desc.kind) {
24 is PolymorphicKind -> WriteMode.POLY_OBJ
25 StructureKind.LIST -> WriteMode.LIST
26 StructureKind.MAP -> selectMapMode(desc, { WriteMode.MAP }, { WriteMode.LIST })
27 else -> WriteMode.OBJ
28 }
29
30 @OptIn(ExperimentalSerializationApi::class)
selectMapModenull31 internal inline fun <T, R1 : T, R2 : T> Json.selectMapMode(
32 mapDescriptor: SerialDescriptor,
33 ifMap: () -> R1,
34 ifList: () -> R2
35 ): T {
36 val keyDescriptor = mapDescriptor.getElementDescriptor(0).carrierDescriptor(serializersModule)
37 val keyKind = keyDescriptor.kind
38
39 return if (keyKind is PrimitiveKind || keyKind == SerialKind.ENUM) {
40 ifMap()
41 } else if (configuration.allowStructuredMapKeys) {
42 ifList()
43 } else {
44 throw InvalidKeyKindException(keyDescriptor)
45 }
46 }
47
carrierDescriptornull48 internal fun SerialDescriptor.carrierDescriptor(module: SerializersModule): SerialDescriptor = when {
49 kind == SerialKind.CONTEXTUAL -> module.getContextualDescriptor(this)?.carrierDescriptor(module) ?: this
50 isInline -> getElementDescriptor(0).carrierDescriptor(module)
51 else -> this
52 }
53