summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Shanshin <sergey.shanshin@jetbrains.com>2022-06-16 14:27:03 +0300
committerGitHub <noreply@github.com>2022-06-16 14:27:03 +0300
commit4b6410019b03c0f816ea75cd8f3ee6b25341e2d9 (patch)
treec96845e351eb5473d14edce0f4881ae4f4c64ffe
parent74072c5d4fa72aa253962af72fe16a7ac2c755e6 (diff)
downloadkotlinx.serialization-4b6410019b03c0f816ea75cd8f3ee6b25341e2d9.tar.gz
Added support for the `kotlin.time.Duration` class as built-in
-rw-r--r--core/api/kotlinx-serialization-core.api10
-rw-r--r--core/commonMain/src/kotlinx/serialization/builtins/BuiltinSerializers.kt9
-rw-r--r--core/commonMain/src/kotlinx/serialization/internal/BuiltInSerializers.kt25
-rw-r--r--core/commonMain/src/kotlinx/serialization/internal/Primitives.kt4
-rw-r--r--core/commonTest/src/kotlinx/serialization/BasicTypesSerializationTest.kt23
-rw-r--r--formats/json/commonTest/src/kotlinx/serialization/SerializersLookupTest.kt8
-rw-r--r--formats/json/commonTest/src/kotlinx/serialization/features/DurationTest.kt27
7 files changed, 104 insertions, 2 deletions
diff --git a/core/api/kotlinx-serialization-core.api b/core/api/kotlinx-serialization-core.api
index 4ec311ba..8d5e9a7f 100644
--- a/core/api/kotlinx-serialization-core.api
+++ b/core/api/kotlinx-serialization-core.api
@@ -175,6 +175,7 @@ public final class kotlinx/serialization/builtins/BuiltinSerializersKt {
public static final fun serializer (Lkotlin/jvm/internal/LongCompanionObject;)Lkotlinx/serialization/KSerializer;
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 final class kotlinx/serialization/builtins/LongAsStringSerializer : kotlinx/serialization/KSerializer {
@@ -662,6 +663,15 @@ public final class kotlinx/serialization/internal/DoubleSerializer : kotlinx/ser
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
}
+public final class kotlinx/serialization/internal/DurationSerializer : kotlinx/serialization/KSerializer {
+ public static final field INSTANCE Lkotlinx/serialization/internal/DurationSerializer;
+ public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+ public fun deserialize-5sfh64U (Lkotlinx/serialization/encoding/Decoder;)J
+ public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+ public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+ public fun serialize-HG0u8IE (Lkotlinx/serialization/encoding/Encoder;J)V
+}
+
public final class kotlinx/serialization/internal/ElementMarker {
public fun <init> (Lkotlinx/serialization/descriptors/SerialDescriptor;Lkotlin/jvm/functions/Function2;)V
public final fun mark (I)V
diff --git a/core/commonMain/src/kotlinx/serialization/builtins/BuiltinSerializers.kt b/core/commonMain/src/kotlinx/serialization/builtins/BuiltinSerializers.kt
index 147f25d9..ddc42783 100644
--- a/core/commonMain/src/kotlinx/serialization/builtins/BuiltinSerializers.kt
+++ b/core/commonMain/src/kotlinx/serialization/builtins/BuiltinSerializers.kt
@@ -9,6 +9,7 @@ import kotlinx.serialization.*
import kotlinx.serialization.internal.*
import kotlin.reflect.*
import kotlinx.serialization.descriptors.*
+import kotlin.time.Duration
/**
* Returns a nullable serializer for the given serializer of non-null type.
@@ -217,3 +218,11 @@ public fun UByte.Companion.serializer(): KSerializer<UByte> = UByteSerializer
@ExperimentalSerializationApi
@ExperimentalUnsignedTypes
public fun UShort.Companion.serializer(): KSerializer<UShort> = UShortSerializer
+
+/**
+ * Returns serializer for [Duration].
+ * It is serialized as a string that represents a duration in the ISO-8601 format.
+ *
+ * The result of serialization is similar to calling [Duration.toIsoString], for deserialization is [Duration.parseIsoString].
+ */
+public fun Duration.Companion.serializer(): KSerializer<Duration> = DurationSerializer
diff --git a/core/commonMain/src/kotlinx/serialization/internal/BuiltInSerializers.kt b/core/commonMain/src/kotlinx/serialization/internal/BuiltInSerializers.kt
new file mode 100644
index 00000000..13735ee7
--- /dev/null
+++ b/core/commonMain/src/kotlinx/serialization/internal/BuiltInSerializers.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+package kotlinx.serialization.internal
+
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.descriptors.PrimitiveKind
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
+import kotlin.time.Duration
+
+
+@PublishedApi
+internal object DurationSerializer : KSerializer<Duration> {
+ override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("kotlin.time.Duration", PrimitiveKind.STRING)
+
+ override fun serialize(encoder: Encoder, value: Duration) {
+ encoder.encodeString(value.toIsoString())
+ }
+
+ override fun deserialize(decoder: Decoder): Duration {
+ return Duration.parseIsoString(decoder.decodeString())
+ }
+}
diff --git a/core/commonMain/src/kotlinx/serialization/internal/Primitives.kt b/core/commonMain/src/kotlinx/serialization/internal/Primitives.kt
index ab127ffa..dfc9aafa 100644
--- a/core/commonMain/src/kotlinx/serialization/internal/Primitives.kt
+++ b/core/commonMain/src/kotlinx/serialization/internal/Primitives.kt
@@ -13,6 +13,7 @@ import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlin.native.concurrent.*
import kotlin.reflect.*
+import kotlin.time.Duration
@SharedImmutable
private val BUILTIN_SERIALIZERS = mapOf(
@@ -33,7 +34,8 @@ private val BUILTIN_SERIALIZERS = mapOf(
ByteArray::class to ByteArraySerializer(),
Boolean::class to Boolean.serializer(),
BooleanArray::class to BooleanArraySerializer(),
- Unit::class to Unit.serializer()
+ Unit::class to Unit.serializer(),
+ Duration::class to Duration.serializer()
)
internal class PrimitiveSerialDescriptor(
diff --git a/core/commonTest/src/kotlinx/serialization/BasicTypesSerializationTest.kt b/core/commonTest/src/kotlinx/serialization/BasicTypesSerializationTest.kt
index 82cbb2ae..dc443fd2 100644
--- a/core/commonTest/src/kotlinx/serialization/BasicTypesSerializationTest.kt
+++ b/core/commonTest/src/kotlinx/serialization/BasicTypesSerializationTest.kt
@@ -4,12 +4,13 @@
package kotlinx.serialization
+import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlinx.serialization.encoding.CompositeDecoder.Companion.UNKNOWN_NAME
-import kotlinx.serialization.internal.*
import kotlinx.serialization.modules.*
import kotlin.test.*
+import kotlin.time.Duration
/*
* Test ensures that type that aggregate all basic (primitive/collection/maps/arrays)
@@ -170,4 +171,24 @@ class BasicTypesSerializationTest {
assertEquals(umbrellaInstance, other)
assertNotSame(umbrellaInstance, other)
}
+
+ @Test
+ fun testEncodeDuration() {
+ val sb = StringBuilder()
+ val out = KeyValueOutput(sb)
+
+ val duration = Duration.parseIsoString("P4DT12H30M5S")
+ out.encodeSerializableValue(Duration.serializer(), duration)
+
+ assertEquals("\"${duration.toIsoString()}\"", sb.toString())
+ }
+
+ @Test
+ fun testDecodeDuration() {
+ val durationString = "P4DT12H30M5S"
+ val inp = KeyValueInput(Parser(StringReader("\"$durationString\"")))
+ val other = inp.decodeSerializableValue(Duration.serializer())
+ assertEquals(Duration.parseIsoString(durationString), other)
+ }
+
}
diff --git a/formats/json/commonTest/src/kotlinx/serialization/SerializersLookupTest.kt b/formats/json/commonTest/src/kotlinx/serialization/SerializersLookupTest.kt
index 18a69404..c5dcf201 100644
--- a/formats/json/commonTest/src/kotlinx/serialization/SerializersLookupTest.kt
+++ b/formats/json/commonTest/src/kotlinx/serialization/SerializersLookupTest.kt
@@ -14,6 +14,7 @@ import kotlinx.serialization.modules.*
import kotlinx.serialization.test.*
import kotlin.reflect.*
import kotlin.test.*
+import kotlin.time.Duration
@Suppress("RemoveExplicitTypeArguments") // This is exactly what's being tested
class SerializersLookupTest : JsonTestBase() {
@@ -243,6 +244,13 @@ class SerializersLookupTest : JsonTestBase() {
}
}
+// TODO uncomment when Kotlin 1.7.20 is released
+// @Test
+// fun testLookupDuration() = noLegacyJs {
+// assertNotNull(serializerOrNull(typeOf<Duration>()))
+// assertSame(Duration.serializer(), serializer<Duration>())
+// }
+
private inline fun <reified T> assertSerializedWithType(
expected: String,
value: T,
diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/DurationTest.kt b/formats/json/commonTest/src/kotlinx/serialization/features/DurationTest.kt
new file mode 100644
index 00000000..a94ae43f
--- /dev/null
+++ b/formats/json/commonTest/src/kotlinx/serialization/features/DurationTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.serialization.features
+
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.json.JsonTestBase
+import kotlin.test.Test
+import kotlin.time.Duration
+import kotlin.time.DurationUnit
+import kotlin.time.toDuration
+
+
+class DurationTest : JsonTestBase() {
+// TODO uncomment when Kotlin 1.7.20 is released
+// @Serializable
+// data class DurationHolder(val duration: Duration)
+// @Test
+// fun testDuration() {
+// assertJsonFormAndRestored(
+// DurationHolder.serializer(),
+// DurationHolder(1000.toDuration(DurationUnit.SECONDS)),
+// """{"duration":"PT16M40S"}"""
+// )
+// }
+}