Skip to content

Commit

Permalink
Split legacy Firestore Timestamp serializer into legacy (java.util.Da…
Browse files Browse the repository at this point in the history
…te) and new (kotlinx.datetime.Instant) one
  • Loading branch information
janseeger committed Apr 5, 2024
1 parent 21526e5 commit 5244e54
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package de.sipgate.federmappe.common

import de.sipgate.federmappe.common.serializers.TimestampSerializer
import de.sipgate.federmappe.common.serializers.TimestampToDateSerializer
import de.sipgate.federmappe.common.serializers.UriSerializer
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.contextual

val DefaultSerializersModule = SerializersModule {
contextual(TimestampSerializer)
contextual(TimestampToDateSerializer)
contextual(UriSerializer)
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.encoding.decodeStructure
import kotlinx.serialization.encoding.encodeStructure

object TimestampSerializer : KSerializer<Date> {
object TimestampToDateSerializer : KSerializer<Date> {
override val descriptor = buildClassSerialDescriptor(serialName = "FirebaseTimestamp") {
element<Long>("seconds")
element<Int>("nanoseconds")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package de.sipgate.federmappe.common.serializers

import kotlin.properties.Delegates
import kotlinx.datetime.Instant
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
import kotlinx.serialization.descriptors.element
import kotlinx.serialization.encoding.CompositeDecoder
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.encoding.decodeStructure
import kotlinx.serialization.encoding.encodeStructure

object TimestampToInstantSerializer : KSerializer<Instant> {
override val descriptor = buildClassSerialDescriptor(serialName = "FirebaseTimestamp") {
element<Long>("seconds")
element<Int>("nanoseconds")
}

override fun serialize(encoder: Encoder, value: Instant) = encoder.encodeStructure(descriptor) {
encodeLongElement(descriptor, 0, value.epochSeconds / 1000)
encodeIntElement(descriptor, 1, value.nanosecondsOfSecond)
}

@ExperimentalSerializationApi
override fun deserialize(decoder: Decoder): Instant {
return decoder.decodeStructure(descriptor = descriptor) {
if (decodeSequentially()) {
val seconds = decodeLongElement(descriptor, 0)
val nanoSeconds = decodeIntElement(descriptor, 1)
Instant.fromEpochSeconds(seconds, nanoSeconds)
} else {
var seconds by Delegates.notNull<Long>()
var nanoSeconds by Delegates.notNull<Int>()

while (true) {
when (val index = decodeElementIndex(descriptor)) {
0 -> seconds = decodeLongElement(descriptor, 0)
1 -> nanoSeconds = decodeIntElement(descriptor, 1)
CompositeDecoder.DECODE_DONE -> break
else -> error("Unexpected index: $index")
}
}

Instant.fromEpochSeconds(seconds, nanoSeconds)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test


class TimestampSerializerTest {
class TimestampToDateSerializerTest {
private val epochSeconds = 1707833611L * 1000
private val nanos = 801 / 1000000

Expand All @@ -20,7 +20,7 @@ class TimestampSerializerTest {
@Test
fun testDeserialization() {
@Serializable
data class TestClass(val a: @Serializable(with = TimestampSerializer::class) Date)
data class TestClass(val a: @Serializable(with = TimestampToDateSerializer::class) Date)

val serializer = serializer<TestClass>()
val data = mapOf<String, Any?>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package de.sipgate.federmappe.firestore

import com.google.firebase.Timestamp
import de.sipgate.federmappe.common.StringMapToObjectDecoder
import de.sipgate.federmappe.common.serializers.TimestampSerializer
import de.sipgate.federmappe.common.serializers.TimestampToDateSerializer
import java.util.Date
import java.util.GregorianCalendar
import kotlinx.serialization.Contextual
Expand Down Expand Up @@ -36,7 +36,7 @@ class FirebaseTimestampTests {
StringMapToObjectDecoder(
data,
ignoreUnknownProperties = true,
serializersModule = SerializersModule { contextual(TimestampSerializer) },
serializersModule = SerializersModule { contextual(TimestampToDateSerializer) },
subtypeDecoder = { (it as? Timestamp)?.let(::FirebaseTimestampDecoder) }
),
)
Expand All @@ -51,7 +51,7 @@ class FirebaseTimestampTests {
// Arrange
@Serializable
data class TestClass(
@Serializable(with = TimestampSerializer::class) val a: Date,
@Serializable(with = TimestampToDateSerializer::class) val a: Date,
)

val serializer = serializer<TestClass>()
Expand Down Expand Up @@ -95,7 +95,7 @@ class FirebaseTimestampTests {
StringMapToObjectDecoder(
data,
ignoreUnknownProperties = true,
serializersModule = SerializersModule { contextual(TimestampSerializer) },
serializersModule = SerializersModule { contextual(TimestampToDateSerializer) },
subtypeDecoder = { (it as? Timestamp)?.let(::FirebaseTimestampDecoder) }
),
)
Expand Down Expand Up @@ -125,7 +125,7 @@ class FirebaseTimestampTests {
StringMapToObjectDecoder(
data,
ignoreUnknownProperties = true,
serializersModule = SerializersModule { contextual(TimestampSerializer) },
serializersModule = SerializersModule { contextual(TimestampToDateSerializer) },
),
)

Expand Down Expand Up @@ -157,7 +157,7 @@ class FirebaseTimestampTests {
StringMapToObjectDecoder(
data,
ignoreUnknownProperties = true,
serializersModule = SerializersModule { contextual(TimestampSerializer) },
serializersModule = SerializersModule { contextual(TimestampToDateSerializer) },
subtypeDecoder = { (it as? Timestamp)?.let(::FirebaseTimestampDecoder) }
),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package de.sipgate.federmappe.firestore.serializers
import com.google.firebase.Timestamp
import de.sipgate.federmappe.firestore.FirebaseTimestampDecoder
import de.sipgate.federmappe.common.StringMapToObjectDecoder
import de.sipgate.federmappe.common.serializers.TimestampSerializer
import de.sipgate.federmappe.common.serializers.TimestampToDateSerializer
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.serializer
Expand All @@ -12,7 +12,7 @@ import org.junit.jupiter.api.Test
import java.util.Date


class TimestampSerializerTest {
class TimestampToDateSerializerTest {
private val epochSeconds = 1707833611L * 1000
private val nanos = 801 / 1000000

Expand All @@ -23,7 +23,7 @@ class TimestampSerializerTest {
@Test
fun testDeserialization() {
@Serializable
data class TestClass(val a: @Serializable(with = TimestampSerializer::class) Date)
data class TestClass(val a: @Serializable(with = TimestampToDateSerializer::class) Date)

val serializer = serializer<TestClass>()
val data = mapOf<String, Any?>("a" to Timestamp(1707833611, 801))
Expand Down

0 comments on commit 5244e54

Please sign in to comment.