Skip to content

Commit

Permalink
Add serializer for kotlin.uuid.Uuid
Browse files Browse the repository at this point in the history
in a simple .toString()/.parse() form.

It is expected to be added as a standard serializer to the Kotlin 2.1 serialization plugin.

Fixes #2730
  • Loading branch information
sandwwraith committed Jul 12, 2024
1 parent 6886e34 commit 5d190b4
Show file tree
Hide file tree
Showing 15 changed files with 99 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ kotlin {
progressiveMode = true

optIn("kotlin.ExperimentalMultiplatform")
optIn("kotlin.ExperimentalStdlibApi")
optIn("kotlinx.serialization.InternalSerializationApi")
}
}
Expand Down
10 changes: 10 additions & 0 deletions core/api/kotlinx-serialization-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ public final class kotlinx/serialization/builtins/BuiltinSerializersKt {
public static final fun serializer (Lkotlin/jvm/internal/ShortCompanionObject;)Lkotlinx/serialization/KSerializer;
public static final fun serializer (Lkotlin/jvm/internal/StringCompanionObject;)Lkotlinx/serialization/KSerializer;
public static final fun serializer (Lkotlin/time/Duration$Companion;)Lkotlinx/serialization/KSerializer;
public static final fun serializer (Lkotlin/uuid/Uuid$Companion;)Lkotlinx/serialization/KSerializer;
}

public final class kotlinx/serialization/builtins/LongAsStringSerializer : kotlinx/serialization/KSerializer {
Expand Down Expand Up @@ -1293,6 +1294,15 @@ public final class kotlinx/serialization/internal/UnitSerializer : kotlinx/seria
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlin/Unit;)V
}

public final class kotlinx/serialization/internal/UuidSerializer : kotlinx/serialization/KSerializer {
public static final field INSTANCE Lkotlinx/serialization/internal/UuidSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlin/uuid/Uuid;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlin/uuid/Uuid;)V
}

public final class kotlinx/serialization/modules/PolymorphicModuleBuilder {
public fun <init> (Lkotlin/reflect/KClass;Lkotlinx/serialization/KSerializer;)V
public synthetic fun <init> (Lkotlin/reflect/KClass;Lkotlinx/serialization/KSerializer;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
Expand Down
16 changes: 7 additions & 9 deletions core/api/kotlinx-serialization-core.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@ final class kotlinx.serialization/UnknownFieldException : kotlinx.serialization/
constructor <init>(kotlin/Int) // kotlinx.serialization/UnknownFieldException.<init>|<init>(kotlin.Int){}[0]
}
final fun (kotlin.time/Duration.Companion).kotlinx.serialization.builtins/serializer(): kotlinx.serialization/KSerializer<kotlin.time/Duration> // kotlinx.serialization.builtins/serializer|[email protected](){}[0]
final fun (kotlin.uuid/Uuid.Companion).kotlinx.serialization.builtins/serializer(): kotlinx.serialization/KSerializer<kotlin.uuid/Uuid> // kotlinx.serialization.builtins/serializer|[email protected](){}[0]
final fun (kotlin/Boolean.Companion).kotlinx.serialization.builtins/serializer(): kotlinx.serialization/KSerializer<kotlin/Boolean> // kotlinx.serialization.builtins/serializer|[email protected](){}[0]
final fun (kotlin/Byte.Companion).kotlinx.serialization.builtins/serializer(): kotlinx.serialization/KSerializer<kotlin/Byte> // kotlinx.serialization.builtins/serializer|[email protected](){}[0]
final fun (kotlin/Char.Companion).kotlinx.serialization.builtins/serializer(): kotlinx.serialization/KSerializer<kotlin/Char> // kotlinx.serialization.builtins/serializer|[email protected](){}[0]
Expand Down Expand Up @@ -747,6 +748,12 @@ final object kotlinx.serialization.internal/UnitSerializer : kotlinx.serializati
final val descriptor // kotlinx.serialization.internal/UnitSerializer.descriptor|{}descriptor[0]
final fun <get-descriptor>(): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.serialization.internal/UnitSerializer.descriptor.<get-descriptor>|<get-descriptor>(){}[0]
}
final object kotlinx.serialization.internal/UuidSerializer : kotlinx.serialization/KSerializer<kotlin.uuid/Uuid> { // kotlinx.serialization.internal/UuidSerializer|null[0]
final fun deserialize(kotlinx.serialization.encoding/Decoder): kotlin.uuid/Uuid // kotlinx.serialization.internal/UuidSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0]
final fun serialize(kotlinx.serialization.encoding/Encoder, kotlin.uuid/Uuid) // kotlinx.serialization.internal/UuidSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlin.uuid.Uuid){}[0]
final val descriptor // kotlinx.serialization.internal/UuidSerializer.descriptor|{}descriptor[0]
final fun <get-descriptor>(): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.serialization.internal/UuidSerializer.descriptor.<get-descriptor>|<get-descriptor>(){}[0]
}
final val kotlinx.serialization.builtins/nullable // kotlinx.serialization.builtins/nullable|@kotlinx.serialization.KSerializer<0:0>{0§<kotlin.Any>}nullable[0]
final fun <#A1: kotlin/Any> (kotlinx.serialization/KSerializer<#A1>).<get-nullable>(): kotlinx.serialization/KSerializer<#A1?> // kotlinx.serialization.builtins/nullable.<get-nullable>|<get-nullable>@kotlinx.serialization.KSerializer<0:0>(){0§<kotlin.Any>}[0]
final val kotlinx.serialization.descriptors/capturedKClass // kotlinx.serialization.descriptors/capturedKClass|@kotlinx.serialization.descriptors.SerialDescriptor{}capturedKClass[0]
Expand Down Expand Up @@ -871,7 +878,6 @@ sealed class <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin.coll
abstract fun (#D).insertKeyValuePair(kotlin/Int, #A, #B) // kotlinx.serialization.internal/MapLikeSerializer.insertKeyValuePair|insertKeyValuePair@1:3(kotlin.Int;1:0;1:1){}[0]
abstract val descriptor // kotlinx.serialization.internal/MapLikeSerializer.descriptor|{}descriptor[0]
abstract fun <get-descriptor>(): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.serialization.internal/MapLikeSerializer.descriptor.<get-descriptor>|<get-descriptor>(){}[0]
constructor <init>(kotlinx.serialization/KSerializer<#A>, kotlinx.serialization/KSerializer<#B>) // kotlinx.serialization.internal/MapLikeSerializer.<init>|<init>(kotlinx.serialization.KSerializer<1:0>;kotlinx.serialization.KSerializer<1:1>){}[0]
final fun readAll(kotlinx.serialization.encoding/CompositeDecoder, #D, kotlin/Int, kotlin/Int) // kotlinx.serialization.internal/MapLikeSerializer.readAll|readAll(kotlinx.serialization.encoding.CompositeDecoder;1:3;kotlin.Int;kotlin.Int){}[0]
final fun readElement(kotlinx.serialization.encoding/CompositeDecoder, kotlin/Int, #D, kotlin/Boolean) // kotlinx.serialization.internal/MapLikeSerializer.readElement|readElement(kotlinx.serialization.encoding.CompositeDecoder;kotlin.Int;1:3;kotlin.Boolean){}[0]
final val keySerializer // kotlinx.serialization.internal/MapLikeSerializer.keySerializer|{}keySerializer[0]
Expand All @@ -891,15 +897,13 @@ sealed class <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> kotlinx.seriali
abstract fun readAll(kotlinx.serialization.encoding/CompositeDecoder, #C, kotlin/Int, kotlin/Int) // kotlinx.serialization.internal/AbstractCollectionSerializer.readAll|readAll(kotlinx.serialization.encoding.CompositeDecoder;1:2;kotlin.Int;kotlin.Int){}[0]
abstract fun readElement(kotlinx.serialization.encoding/CompositeDecoder, kotlin/Int, #C, kotlin/Boolean = ...) // kotlinx.serialization.internal/AbstractCollectionSerializer.readElement|readElement(kotlinx.serialization.encoding.CompositeDecoder;kotlin.Int;1:2;kotlin.Boolean){}[0]
abstract fun serialize(kotlinx.serialization.encoding/Encoder, #B) // kotlinx.serialization.internal/AbstractCollectionSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;1:1){}[0]
constructor <init>() // kotlinx.serialization.internal/AbstractCollectionSerializer.<init>|<init>(){}[0]
final fun merge(kotlinx.serialization.encoding/Decoder, #B?): #B // kotlinx.serialization.internal/AbstractCollectionSerializer.merge|merge(kotlinx.serialization.encoding.Decoder;1:1?){}[0]
open fun deserialize(kotlinx.serialization.encoding/Decoder): #B // kotlinx.serialization.internal/AbstractCollectionSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0]
}
sealed class <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> kotlinx.serialization.internal/CollectionLikeSerializer : kotlinx.serialization.internal/AbstractCollectionSerializer<#A, #B, #C> { // kotlinx.serialization.internal/CollectionLikeSerializer|null[0]
abstract fun (#C).insert(kotlin/Int, #A) // kotlinx.serialization.internal/CollectionLikeSerializer.insert|insert@1:2(kotlin.Int;1:0){}[0]
abstract val descriptor // kotlinx.serialization.internal/CollectionLikeSerializer.descriptor|{}descriptor[0]
abstract fun <get-descriptor>(): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.serialization.internal/CollectionLikeSerializer.descriptor.<get-descriptor>|<get-descriptor>(){}[0]
constructor <init>(kotlinx.serialization/KSerializer<#A>) // kotlinx.serialization.internal/CollectionLikeSerializer.<init>|<init>(kotlinx.serialization.KSerializer<1:0>){}[0]
final fun readAll(kotlinx.serialization.encoding/CompositeDecoder, #C, kotlin/Int, kotlin/Int) // kotlinx.serialization.internal/CollectionLikeSerializer.readAll|readAll(kotlinx.serialization.encoding.CompositeDecoder;1:2;kotlin.Int;kotlin.Int){}[0]
open fun readElement(kotlinx.serialization.encoding/CompositeDecoder, kotlin/Int, #C, kotlin/Boolean) // kotlinx.serialization.internal/CollectionLikeSerializer.readElement|readElement(kotlinx.serialization.encoding.CompositeDecoder;kotlin.Int;1:2;kotlin.Boolean){}[0]
open fun serialize(kotlinx.serialization.encoding/Encoder, #B) // kotlinx.serialization.internal/CollectionLikeSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;1:1){}[0]
Expand All @@ -910,7 +914,6 @@ sealed class <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> kotlinx.seriali
abstract fun (#C).<get-key>(): #A // kotlinx.serialization.internal/KeyValueSerializer.key.<get-key>|<get-key>@1:2(){}[0]
abstract val value // kotlinx.serialization.internal/KeyValueSerializer.value|@1:2{}value[0]
abstract fun (#C).<get-value>(): #B // kotlinx.serialization.internal/KeyValueSerializer.value.<get-value>|<get-value>@1:2(){}[0]
constructor <init>(kotlinx.serialization/KSerializer<#A>, kotlinx.serialization/KSerializer<#B>) // kotlinx.serialization.internal/KeyValueSerializer.<init>|<init>(kotlinx.serialization.KSerializer<1:0>;kotlinx.serialization.KSerializer<1:1>){}[0]
final val keySerializer // kotlinx.serialization.internal/KeyValueSerializer.keySerializer|{}keySerializer[0]
final fun <get-keySerializer>(): kotlinx.serialization/KSerializer<#A> // kotlinx.serialization.internal/KeyValueSerializer.keySerializer.<get-keySerializer>|<get-keySerializer>(){}[0]
final val valueSerializer // kotlinx.serialization.internal/KeyValueSerializer.valueSerializer|{}valueSerializer[0]
Expand All @@ -919,12 +922,10 @@ sealed class <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> kotlinx.seriali
open fun serialize(kotlinx.serialization.encoding/Encoder, #C) // kotlinx.serialization.internal/KeyValueSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;1:2){}[0]
}
sealed class kotlinx.serialization.descriptors/PolymorphicKind : kotlinx.serialization.descriptors/SerialKind { // kotlinx.serialization.descriptors/PolymorphicKind|null[0]
constructor <init>() // kotlinx.serialization.descriptors/PolymorphicKind.<init>|<init>(){}[0]
final object OPEN : kotlinx.serialization.descriptors/PolymorphicKind // kotlinx.serialization.descriptors/PolymorphicKind.OPEN|null[0]
final object SEALED : kotlinx.serialization.descriptors/PolymorphicKind // kotlinx.serialization.descriptors/PolymorphicKind.SEALED|null[0]
}
sealed class kotlinx.serialization.descriptors/PrimitiveKind : kotlinx.serialization.descriptors/SerialKind { // kotlinx.serialization.descriptors/PrimitiveKind|null[0]
constructor <init>() // kotlinx.serialization.descriptors/PrimitiveKind.<init>|<init>(){}[0]
final object BOOLEAN : kotlinx.serialization.descriptors/PrimitiveKind // kotlinx.serialization.descriptors/PrimitiveKind.BOOLEAN|null[0]
final object BYTE : kotlinx.serialization.descriptors/PrimitiveKind // kotlinx.serialization.descriptors/PrimitiveKind.BYTE|null[0]
final object CHAR : kotlinx.serialization.descriptors/PrimitiveKind // kotlinx.serialization.descriptors/PrimitiveKind.CHAR|null[0]
Expand All @@ -936,14 +937,12 @@ sealed class kotlinx.serialization.descriptors/PrimitiveKind : kotlinx.serializa
final object STRING : kotlinx.serialization.descriptors/PrimitiveKind // kotlinx.serialization.descriptors/PrimitiveKind.STRING|null[0]
}
sealed class kotlinx.serialization.descriptors/SerialKind { // kotlinx.serialization.descriptors/SerialKind|null[0]
constructor <init>() // kotlinx.serialization.descriptors/SerialKind.<init>|<init>(){}[0]
final object CONTEXTUAL : kotlinx.serialization.descriptors/SerialKind // kotlinx.serialization.descriptors/SerialKind.CONTEXTUAL|null[0]
final object ENUM : kotlinx.serialization.descriptors/SerialKind // kotlinx.serialization.descriptors/SerialKind.ENUM|null[0]
open fun hashCode(): kotlin/Int // kotlinx.serialization.descriptors/SerialKind.hashCode|hashCode(){}[0]
open fun toString(): kotlin/String // kotlinx.serialization.descriptors/SerialKind.toString|toString(){}[0]
}
sealed class kotlinx.serialization.descriptors/StructureKind : kotlinx.serialization.descriptors/SerialKind { // kotlinx.serialization.descriptors/StructureKind|null[0]
constructor <init>() // kotlinx.serialization.descriptors/StructureKind.<init>|<init>(){}[0]
final object CLASS : kotlinx.serialization.descriptors/StructureKind // kotlinx.serialization.descriptors/StructureKind.CLASS|null[0]
final object LIST : kotlinx.serialization.descriptors/StructureKind // kotlinx.serialization.descriptors/StructureKind.LIST|null[0]
final object MAP : kotlinx.serialization.descriptors/StructureKind // kotlinx.serialization.descriptors/StructureKind.MAP|null[0]
Expand All @@ -954,7 +953,6 @@ sealed class kotlinx.serialization.modules/SerializersModule { // kotlinx.serial
abstract fun <#A1: kotlin/Any> getPolymorphic(kotlin.reflect/KClass<in #A1>, #A1): kotlinx.serialization/SerializationStrategy<#A1>? // kotlinx.serialization.modules/SerializersModule.getPolymorphic|getPolymorphic(kotlin.reflect.KClass<in|0:0>;0:0){0§<kotlin.Any>}[0]
abstract fun <#A1: kotlin/Any> getPolymorphic(kotlin.reflect/KClass<in #A1>, kotlin/String?): kotlinx.serialization/DeserializationStrategy<#A1>? // kotlinx.serialization.modules/SerializersModule.getPolymorphic|getPolymorphic(kotlin.reflect.KClass<in|0:0>;kotlin.String?){0§<kotlin.Any>}[0]
abstract fun dumpTo(kotlinx.serialization.modules/SerializersModuleCollector) // kotlinx.serialization.modules/SerializersModule.dumpTo|dumpTo(kotlinx.serialization.modules.SerializersModuleCollector){}[0]
constructor <init>() // kotlinx.serialization.modules/SerializersModule.<init>|<init>(){}[0]
final fun <#A1: kotlin/Any> getContextual(kotlin.reflect/KClass<#A1>): kotlinx.serialization/KSerializer<#A1>? // kotlinx.serialization.modules/SerializersModule.getContextual|getContextual(kotlin.reflect.KClass<0:0>){0§<kotlin.Any>}[0]
}
// Targets: [native, wasmJs, wasmWasi]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import kotlinx.serialization.internal.*
import kotlin.reflect.*
import kotlinx.serialization.descriptors.*
import kotlin.time.Duration
import kotlin.uuid.*

/**
* Returns a nullable serializer for the given serializer of non-null type.
Expand Down Expand Up @@ -251,6 +252,20 @@ public fun UShort.Companion.serializer(): KSerializer<UShort> = UShortSerializer
*/
public fun Duration.Companion.serializer(): KSerializer<Duration> = DurationSerializer

/**
* Returns serializer for [Uuid].
* Serializer operates with a standard UUID string representation, also known as "hex-and-dash" format —
* [RFC 9562 section 4](https://www.rfc-editor.org/rfc/rfc9562.html#section-4).
*
* Deserialization is case-insensitive.
* More details can be found in the documentation of [Uuid.toString] and [Uuid.parse] functions.
*
* @see Uuid.toString
* @see Uuid.parse
*/
@ExperimentalStdlibApi
public fun Uuid.Companion.serializer(): KSerializer<Uuid> = UuidSerializer

/**
* Returns serializer for [Nothing].
* Throws an exception when trying to encode or decode.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlin.time.Duration
import kotlin.uuid.*


@PublishedApi
Expand Down Expand Up @@ -37,3 +38,17 @@ internal object NothingSerializer : KSerializer<Nothing> {
throw SerializationException("'kotlin.Nothing' does not have instances")
}
}

@PublishedApi
@ExperimentalStdlibApi
internal object UuidSerializer: KSerializer<Uuid> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("kotlin.uuid.Uuid", PrimitiveKind.STRING)

override fun serialize(encoder: Encoder, value: Uuid) {
encoder.encodeString(value.toString())
}

override fun deserialize(decoder: Decoder): Uuid {
return Uuid.parse(decoder.decodeString())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import kotlinx.serialization.*
import kotlinx.serialization.builtins.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlin.native.concurrent.*
import kotlin.reflect.*
import kotlin.time.Duration
import kotlin.uuid.Uuid

@OptIn(ExperimentalUnsignedTypes::class)
@OptIn(ExperimentalUnsignedTypes::class, ExperimentalStdlibApi::class)
private val BUILTIN_SERIALIZERS = mapOf(
String::class to String.serializer(),
Char::class to Char.serializer(),
Expand Down Expand Up @@ -44,7 +44,8 @@ private val BUILTIN_SERIALIZERS = mapOf(
BooleanArray::class to BooleanArraySerializer(),
Unit::class to Unit.serializer(),
Nothing::class to NothingSerializer(),
Duration::class to Duration.serializer()
Duration::class to Duration.serializer(),
Uuid::class to Uuid.serializer()
)

internal class PrimitiveSerialDescriptor(
Expand Down
1 change: 0 additions & 1 deletion formats/cbor/api/kotlinx-serialization-cbor.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ open annotation class kotlinx.serialization.cbor/ByteString : kotlin/Annotation
constructor <init>() // kotlinx.serialization.cbor/ByteString.<init>|<init>(){}[0]
}
sealed class kotlinx.serialization.cbor/Cbor : kotlinx.serialization/BinaryFormat { // kotlinx.serialization.cbor/Cbor|null[0]
constructor <init>(kotlin/Boolean, kotlin/Boolean, kotlinx.serialization.modules/SerializersModule) // kotlinx.serialization.cbor/Cbor.<init>|<init>(kotlin.Boolean;kotlin.Boolean;kotlinx.serialization.modules.SerializersModule){}[0]
final object Default : kotlinx.serialization.cbor/Cbor // kotlinx.serialization.cbor/Cbor.Default|null[0]
open fun <#A1: kotlin/Any?> decodeFromByteArray(kotlinx.serialization/DeserializationStrategy<#A1>, kotlin/ByteArray): #A1 // kotlinx.serialization.cbor/Cbor.decodeFromByteArray|decodeFromByteArray(kotlinx.serialization.DeserializationStrategy<0:0>;kotlin.ByteArray){0§<kotlin.Any?>}[0]
open fun <#A1: kotlin/Any?> encodeToByteArray(kotlinx.serialization/SerializationStrategy<#A1>, #A1): kotlin/ByteArray // kotlinx.serialization.cbor/Cbor.encodeToByteArray|encodeToByteArray(kotlinx.serialization.SerializationStrategy<0:0>;0:0){0§<kotlin.Any?>}[0]
Expand Down
1 change: 1 addition & 0 deletions formats/json-tests/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ kotlin {
sourceSets {
configureEach {
languageSettings {
optIn("kotlin.ExperimentalStdlibApi")
optIn("kotlinx.serialization.internal.CoreFriendModuleApi")
optIn("kotlinx.serialization.json.internal.JsonFriendModuleApi")
}
Expand Down
Loading

0 comments on commit 5d190b4

Please sign in to comment.