summaryrefslogtreecommitdiff
path: root/core/commonMain/src/kotlinx/serialization/internal/Platform.common.kt
diff options
context:
space:
mode:
Diffstat (limited to 'core/commonMain/src/kotlinx/serialization/internal/Platform.common.kt')
-rw-r--r--core/commonMain/src/kotlinx/serialization/internal/Platform.common.kt72
1 files changed, 53 insertions, 19 deletions
diff --git a/core/commonMain/src/kotlinx/serialization/internal/Platform.common.kt b/core/commonMain/src/kotlinx/serialization/internal/Platform.common.kt
index fde2c36a..ef313ccd 100644
--- a/core/commonMain/src/kotlinx/serialization/internal/Platform.common.kt
+++ b/core/commonMain/src/kotlinx/serialization/internal/Platform.common.kt
@@ -21,7 +21,7 @@ internal object InternalHexConverter {
while (i < len) {
val h = hexToInt(s[i])
val l = hexToInt(s[i + 1])
- require(!(h == -1 || l == -1)) { "Invalid hex chars: ${s[i]}${s[i+1]}" }
+ require(!(h == -1 || l == -1)) { "Invalid hex chars: ${s[i]}${s[i + 1]}" }
bytes[i / 2] = ((h shl 4) + l).toByte()
i += 2
@@ -65,7 +65,6 @@ internal fun SerialDescriptor.cachedSerialNames(): Set<String> {
return result
}
-@SharedImmutable
private val EMPTY_DESCRIPTOR_ARRAY: Array<SerialDescriptor> = arrayOf()
/**
@@ -85,28 +84,40 @@ internal inline fun <T> SerializationStrategy<*>.cast(): SerializationStrategy<T
@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
@PublishedApi
-internal inline fun <T> DeserializationStrategy<*>.cast(): DeserializationStrategy<T> = this as DeserializationStrategy<T>
+internal inline fun <T> DeserializationStrategy<*>.cast(): DeserializationStrategy<T> =
+ this as DeserializationStrategy<T>
internal fun KClass<*>.serializerNotRegistered(): Nothing {
- throw SerializationException(
- "Serializer for class '${simpleName}' is not found.\n" +
- "Mark the class as @Serializable or provide the serializer explicitly."
- )
+ throw SerializationException(notRegisteredMessage())
}
+internal fun KClass<*>.notRegisteredMessage(): String = notRegisteredMessage(simpleName ?: "<local class name not available>")
+
+internal fun notRegisteredMessage(className: String): String = "Serializer for class '$className' is not found.\n" +
+ "Please ensure that class is marked as '@Serializable' and that the serialization compiler plugin is applied.\n"
+
internal expect fun KClass<*>.platformSpecificSerializerNotRegistered(): Nothing
@Suppress("UNCHECKED_CAST")
internal fun KType.kclass() = when (val t = classifier) {
is KClass<*> -> t
is KTypeParameter -> {
- error("Captured type paramerer $t from generic non-reified function. " +
- "Such functionality cannot be supported as $t is erased, either specify serializer explicitly or make " +
- "calling function inline with reified $t")
+ // If you are going to change this error message, please also actualize the message in the compiler intrinsics here:
+ // Kotlin/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializationJvmIrIntrinsicSupport.kt#argumentTypeOrGenerateException
+ throw IllegalArgumentException(
+ "Captured type parameter $t from generic non-reified function. " +
+ "Such functionality cannot be supported because $t is erased, either specify serializer explicitly or make " +
+ "calling function inline with reified $t."
+ )
}
- else -> error("Only KClass supported as classifier, got $t")
+
+ else -> throw IllegalArgumentException("Only KClass supported as classifier, got $t")
} as KClass<Any>
+// If you are going to change this error message, please also actualize the message in the compiler intrinsics here:
+// Kotlin/plugins/kotlinx-serialization/kotlinx-serialization.backend/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializationJvmIrIntrinsicSupport.kt#argumentTypeOrGenerateException
+internal fun KTypeProjection.typeOrThrow(): KType = requireNotNull(type) { "Star projections in type arguments are not allowed, but had $type" }
+
/**
* Constructs KSerializer<D<T0, T1, ...>> by given KSerializer<T0>, KSerializer<T1>, ...
* via reflection (on JVM) or compiler+plugin intrinsic `SerializerFactory` (on Native)
@@ -130,18 +141,41 @@ internal expect fun BooleanArray.getChecked(index: Int): Boolean
internal expect fun <T : Any> KClass<T>.compiledSerializerImpl(): KSerializer<T>?
-internal expect fun <T : Any, E : T?> ArrayList<E>.toNativeArrayImpl(eClass: KClass<T>): Array<E>
+/**
+ * Create serializers cache for non-parametrized and non-contextual serializers.
+ * The activity and type of cache is determined for a specific platform and a specific environment.
+ */
+internal expect fun <T> createCache(factory: (KClass<*>) -> KSerializer<T>?): SerializerCache<T>
/**
- * Checks whether the receiver is an instance of a given kclass.
- *
- * This check is a replacement for [KClass.isInstance] because on JVM it requires kotlin-reflect.jar in classpath (see KT-14720).
- *
- * On JS and Native, this function delegates to aforementioned [KClass.isInstance] since it is supported there out-of-the-box;
- * on JVM, it falls back to `java.lang.Class.isInstance`, which causes difference when applied to function types with big arity.
+ * Create serializers cache for parametrized and non-contextual serializers. Parameters also non-contextual.
+ * The activity and type of cache is determined for a specific platform and a specific environment.
*/
-internal expect fun Any.isInstanceOf(kclass: KClass<*>): Boolean
+internal expect fun <T> createParametrizedCache(factory: (KClass<Any>, List<KType>) -> KSerializer<T>?): ParametrizedSerializerCache<T>
+
+internal expect fun <T : Any, E : T?> ArrayList<E>.toNativeArrayImpl(eClass: KClass<T>): Array<E>
internal inline fun <T, K> Iterable<T>.elementsHashCodeBy(selector: (T) -> K): Int {
return fold(1) { hash, element -> 31 * hash + selector(element).hashCode() }
}
+
+/**
+ * Cache class for non-parametrized and non-contextual serializers.
+ */
+internal interface SerializerCache<T> {
+ /**
+ * Returns cached serializer or `null` if serializer not found.
+ */
+ fun get(key: KClass<Any>): KSerializer<T>?
+}
+
+/**
+ * Cache class for parametrized and non-contextual serializers.
+ */
+internal interface ParametrizedSerializerCache<T> {
+ /**
+ * Returns successful result with cached serializer or `null` if root serializer not found.
+ * If no serializer was found for the parameters, then result contains an exception.
+ */
+ fun get(key: KClass<Any>, types: List<KType> = emptyList()): Result<KSerializer<T>?>
+}