1 /* 2 * Copyright 2017-2020 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.internal 7 8 import kotlinx.serialization.* 9 import kotlinx.serialization.descriptors.* 10 11 @ExperimentalSerializationApi 12 internal sealed class ListLikeDescriptor(val elementDescriptor: SerialDescriptor) : SerialDescriptor { 13 override val kind: SerialKind get() = StructureKind.LIST 14 override val elementsCount: Int = 1 15 getElementNamenull16 override fun getElementName(index: Int): String = index.toString() 17 override fun getElementIndex(name: String): Int = 18 name.toIntOrNull() ?: throw IllegalArgumentException("$name is not a valid list index") 19 20 override fun isElementOptional(index: Int): Boolean { 21 require(index >= 0) { "Illegal index $index, $serialName expects only non-negative indices"} 22 return false 23 } 24 getElementAnnotationsnull25 override fun getElementAnnotations(index: Int): List<Annotation> { 26 require(index >= 0) { "Illegal index $index, $serialName expects only non-negative indices"} 27 return emptyList() 28 } 29 getElementDescriptornull30 override fun getElementDescriptor(index: Int): SerialDescriptor { 31 require(index >= 0) { "Illegal index $index, $serialName expects only non-negative indices"} 32 return elementDescriptor 33 } 34 equalsnull35 override fun equals(other: Any?): Boolean { 36 if (this === other) return true 37 if (other !is ListLikeDescriptor) return false 38 if (elementDescriptor == other.elementDescriptor && serialName == other.serialName) return true 39 return false 40 } 41 hashCodenull42 override fun hashCode(): Int { 43 return elementDescriptor.hashCode() * 31 + serialName.hashCode() 44 } 45 toStringnull46 override fun toString(): String = "$serialName($elementDescriptor)" 47 } 48 49 internal sealed class MapLikeDescriptor( 50 override val serialName: String, 51 val keyDescriptor: SerialDescriptor, 52 val valueDescriptor: SerialDescriptor 53 ) : SerialDescriptor { 54 override val kind: SerialKind get() = StructureKind.MAP 55 override val elementsCount: Int = 2 56 override fun getElementName(index: Int): String = index.toString() 57 override fun getElementIndex(name: String): Int = 58 name.toIntOrNull() ?: throw IllegalArgumentException("$name is not a valid map index") 59 60 override fun isElementOptional(index: Int): Boolean { 61 require(index >= 0) { "Illegal index $index, $serialName expects only non-negative indices"} 62 return false 63 } 64 65 override fun getElementAnnotations(index: Int): List<Annotation> { 66 require(index >= 0) { "Illegal index $index, $serialName expects only non-negative indices"} 67 return emptyList() 68 } 69 70 override fun getElementDescriptor(index: Int): SerialDescriptor { 71 require(index >= 0) { "Illegal index $index, $serialName expects only non-negative indices"} 72 return when (index % 2) { 73 0 -> keyDescriptor 74 1 -> valueDescriptor 75 else -> error("Unreached") 76 } 77 } 78 79 override fun equals(other: Any?): Boolean { 80 if (this === other) return true 81 if (other !is MapLikeDescriptor) return false 82 if (serialName != other.serialName) return false 83 if (keyDescriptor != other.keyDescriptor) return false 84 if (valueDescriptor != other.valueDescriptor) return false 85 return true 86 } 87 88 override fun hashCode(): Int { 89 var result = serialName.hashCode() 90 result = 31 * result + keyDescriptor.hashCode() 91 result = 31 * result + valueDescriptor.hashCode() 92 return result 93 } 94 95 override fun toString(): String = "$serialName($keyDescriptor, $valueDescriptor)" 96 } 97 98 internal const val ARRAY_NAME = "kotlin.Array" 99 internal const val ARRAY_LIST_NAME = "kotlin.collections.ArrayList" 100 internal const val LINKED_HASH_SET_NAME = "kotlin.collections.LinkedHashSet" 101 internal const val HASH_SET_NAME = "kotlin.collections.HashSet" 102 internal const val LINKED_HASH_MAP_NAME = "kotlin.collections.LinkedHashMap" 103 internal const val HASH_MAP_NAME = "kotlin.collections.HashMap" 104 105 /** 106 * Descriptor for primitive arrays, such as [IntArray], [DoubleArray], etc... 107 * 108 * Can be obtained from corresponding serializers (e.g. [ByteArraySerializer.descriptor]) 109 */ 110 @OptIn(ExperimentalSerializationApi::class) 111 internal class PrimitiveArrayDescriptor internal constructor( 112 primitive: SerialDescriptor 113 ) : ListLikeDescriptor(primitive) { 114 override val serialName: String = "${primitive.serialName}Array" 115 } 116 117 internal class ArrayClassDesc(elementDesc: SerialDescriptor) : ListLikeDescriptor(elementDesc) { 118 override val serialName: String get() = ARRAY_NAME 119 } 120 121 internal class ArrayListClassDesc(elementDesc: SerialDescriptor) : ListLikeDescriptor(elementDesc) { 122 override val serialName: String get() = ARRAY_LIST_NAME 123 } 124 125 internal class LinkedHashSetClassDesc(elementDesc: SerialDescriptor) : ListLikeDescriptor(elementDesc) { 126 override val serialName: String get() = LINKED_HASH_SET_NAME 127 } 128 129 internal class HashSetClassDesc(elementDesc: SerialDescriptor) : ListLikeDescriptor(elementDesc) { 130 override val serialName: String get() = HASH_SET_NAME 131 } 132 133 internal class LinkedHashMapClassDesc(keyDesc: SerialDescriptor, valueDesc: SerialDescriptor) : 134 MapLikeDescriptor(LINKED_HASH_MAP_NAME, keyDesc, valueDesc) 135 136 internal class HashMapClassDesc(keyDesc: SerialDescriptor, valueDesc: SerialDescriptor) : 137 MapLikeDescriptor(HASH_MAP_NAME, keyDesc, valueDesc) 138