[PM-19840] Migrate BaseEnumeratedIntSerializer to core module (#4975)

This commit is contained in:
Patrick Honkonen
2025-04-03 12:06:36 -04:00
committed by GitHub
parent 7938c8c2bb
commit 291c568583
20 changed files with 20 additions and 20 deletions

View File

@@ -0,0 +1,46 @@
package com.bitwarden.core.data.serializer
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
/**
* Base [KSerializer] for mapping an [Enum] with possible values given by [values] to/from integer
* values, which should be specified using [SerialName]. If a [default] value is provided, it will
* be used when an unknown value is provided.
*/
@Suppress("UnnecessaryAbstractClass")
abstract class BaseEnumeratedIntSerializer<T : Enum<T>>(
private val className: String,
private val values: Array<T>,
private val default: T? = null,
) : KSerializer<T> {
override val descriptor: SerialDescriptor
get() = PrimitiveSerialDescriptor(
serialName = this::class.java.simpleName,
kind = PrimitiveKind.INT,
)
override fun deserialize(decoder: Decoder): T {
val decodedValue = decoder.decodeInt().toString()
return values.firstOrNull { it.serialNameAnnotation?.value == decodedValue }
?: default
?: throw IllegalArgumentException("Unknown value $decodedValue for $className")
}
override fun serialize(encoder: Encoder, value: T) {
encoder.encodeInt(
requireNotNull(
value.serialNameAnnotation?.value?.toInt(),
),
)
}
private val Enum<*>.serialNameAnnotation: SerialName?
get() = javaClass.getDeclaredField(name).getAnnotation(SerialName::class.java)
}

View File

@@ -0,0 +1,68 @@
package com.bitwarden.core.data.serializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.encodeToJsonElement
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
class BaseEnumeratedIntSerializerTest {
private val json = Json
@Test
fun `properly deserializes integers to enums`() {
assertEquals(
TestEnum.CASE_1,
json.decodeFromString<TestEnum>(
"""
1
""",
),
)
}
@Test
fun `properly serializes enums back to integers`() {
assertEquals(
json.parseToJsonElement(
"""
1
""",
),
json.encodeToJsonElement(
TestEnum.CASE_1,
),
)
}
@Test
fun `properly returns default value when unknown value is provided`() {
assertEquals(
TestEnum.UNKNOWN,
json.decodeFromString<TestEnum>(
"""
-1
""",
),
)
}
}
@Serializable(TestEnumSerializer::class)
private enum class TestEnum {
@SerialName("1")
CASE_1,
@SerialName("2")
CASE_2,
@SerialName("-1")
UNKNOWN,
}
private class TestEnumSerializer : BaseEnumeratedIntSerializer<TestEnum>(
className = "TestEnum",
values = TestEnum.entries.toTypedArray(),
default = TestEnum.UNKNOWN,
)