diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/serializer/BaseEnumeratedIntSerializer.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/serializer/BaseEnumeratedIntSerializer.kt index 0216594e7..109e7f259 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/serializer/BaseEnumeratedIntSerializer.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/serializer/BaseEnumeratedIntSerializer.kt @@ -10,11 +10,13 @@ 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]. + * 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>( private val values: Array, + private val default: T? = null, ) : KSerializer { override val descriptor: SerialDescriptor @@ -25,7 +27,9 @@ abstract class BaseEnumeratedIntSerializer>( override fun deserialize(decoder: Decoder): T { val decodedValue = decoder.decodeInt().toString() - return values.first { it.serialNameAnnotation?.value == decodedValue } + return values.firstOrNull { it.serialNameAnnotation?.value == decodedValue } + ?: default + ?: throw IllegalArgumentException("Unknown value $decodedValue") } override fun serialize(encoder: Encoder, value: T) { diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/model/PolicyTypeJson.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/model/PolicyTypeJson.kt index b9f1207dc..bb74e1bc5 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/model/PolicyTypeJson.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/model/PolicyTypeJson.kt @@ -81,8 +81,19 @@ enum class PolicyTypeJson { */ @SerialName("11") ACTIVATE_AUTOFILL, + + /** + * Represents an unknown policy type. + * + * This is used for forward compatibility to handle new policy types that the client doesn't yet + * understand. + */ + @SerialName("-1") + UNKNOWN, } @Keep -private class PolicyTypeSerializer : - BaseEnumeratedIntSerializer(PolicyTypeJson.entries.toTypedArray()) +private class PolicyTypeSerializer : BaseEnumeratedIntSerializer( + values = PolicyTypeJson.entries.toTypedArray(), + default = PolicyTypeJson.UNKNOWN, +) diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/serializer/BaseEnumeratedIntSerializerTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/serializer/BaseEnumeratedIntSerializerTest.kt index 88457e915..ae9783f39 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/serializer/BaseEnumeratedIntSerializerTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/serializer/BaseEnumeratedIntSerializerTest.kt @@ -35,6 +35,18 @@ class BaseEnumeratedIntSerializerTest { ), ) } + + @Test + fun `properly returns default value when unknown value is provided`() { + assertEquals( + TestEnum.UNKNOWN, + json.decodeFromString( + """ + -1 + """, + ), + ) + } } @Serializable(TestEnumSerializer::class) @@ -44,7 +56,12 @@ private enum class TestEnum { @SerialName("2") CASE_2, + + @SerialName("-1") + UNKNOWN, } -private class TestEnumSerializer : - BaseEnumeratedIntSerializer(values = TestEnum.entries.toTypedArray()) +private class TestEnumSerializer : BaseEnumeratedIntSerializer( + values = TestEnum.entries.toTypedArray(), + default = TestEnum.UNKNOWN, +)