From 94502d446b624a22fa92c179679e2a11cdc2262f Mon Sep 17 00:00:00 2001 From: Him188 Date: Tue, 28 Jan 2020 17:27:28 +0800 Subject: [PATCH] JceStruct serialization: optional elements support --- .../mirai/qqandroid/io/serialization/Jce.kt | 48 +++++++++++++------ .../JceDecoderTest.kt | 2 +- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce.kt index 48888da36..b644180d5 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce.kt @@ -330,6 +330,9 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo override fun decodeTaggedString(tag: Int): String = input.readString(tag) override fun decodeTaggedBoolean(tag: Int): Boolean = input.readBoolean(tag) + + override fun decodeTaggedEnum(tag: Int, enumDescription: SerialDescriptor): Int = + TODO() /** * 在 [KSerializer.serialize] 前 */ @@ -365,16 +368,26 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo } is MapLikeDescriptor -> { - val tag = currentTagOrNull + val tag = currentTagOrNull - if (tag != null && input.skipToTagOrNull(tag) { popTag() } == null && desc.isNullable) { - return NullReader(this.input) - } + if (tag != null && input.skipToTagOrNull(tag) { popTag() } == null && desc.isNullable) { + return NullReader(this.input) + } + if (tag!=null) { + popTag() + } return JceMapReader(input.readInt(0), this.input) } } + if (!input.input.endOfInput) { + val tag = currentTagOrNull + if (tag != null && input.peakHead().tag > tag) { + return NullReader(this.input) + } + } + if (desc.kind == StructureKind.CLASS || desc.kind == UnionKind.OBJECT) { val tag = currentTagOrNull if (tag != null) { @@ -390,18 +403,20 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo return this // top-level } - if (!input.input.endOfInput) { - val tag = currentTagOrNull - if (tag != null && input.peakHead().tag > tag) { - return NullReader(this.input) - } - } - return super.beginStructure(desc, *typeParams) } + override fun decodeTaggedNull(tag: Int): Nothing? { + return null + } + + override fun decodeTaggedNotNullMark(tag: Int): Boolean { + return !input.input.endOfInput && input.peakHead().tag <= tag + } + @Suppress("UNCHECKED_CAST") override fun decodeNullableSerializableValue(deserializer: DeserializationStrategy): T? { + println("decodeNullableSerializableValue: ${deserializer.getClassName()}") if (deserializer is NullReader) { return null } @@ -421,6 +436,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo ) { return input.readByteArray(popTag()).toMutableList() as T } + return super.decodeSerializableValue(deserializer) } is MapLikeDescriptor -> { // 将 mapOf(k1 to v1, k2 to v2, ...) 转换为 listOf(k1, v1, k2, v2, ...) 以便于写入. @@ -430,16 +446,18 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo return setOfEntries.associateBy({ it.key }, { it.value }) as T } } - return super.decodeSerializableValue(deserializer) + val tag = currentTagOrNull ?: return deserializer.deserialize(this) + return if (this.decodeTaggedNotNullMark(tag)){ + deserializer.deserialize(this) + } else { + null + } } @Suppress("UNCHECKED_CAST") override fun decodeSerializableValue(deserializer: DeserializationStrategy): T { return decodeNullableSerializableValue(deserializer as DeserializationStrategy) as? T ?: error("value is not optional but cannot find") } - - override fun decodeTaggedEnum(tag: Int, enumDescription: SerialDescriptor): Int = - TODO() } diff --git a/mirai-core-qqandroid/src/jvmTest/kotlin/net.mamoe.mirai.qqandroid.io.serialization/JceDecoderTest.kt b/mirai-core-qqandroid/src/jvmTest/kotlin/net.mamoe.mirai.qqandroid.io.serialization/JceDecoderTest.kt index 7055955da..875453673 100644 --- a/mirai-core-qqandroid/src/jvmTest/kotlin/net.mamoe.mirai.qqandroid.io.serialization/JceDecoderTest.kt +++ b/mirai-core-qqandroid/src/jvmTest/kotlin/net.mamoe.mirai.qqandroid.io.serialization/JceDecoderTest.kt @@ -72,7 +72,7 @@ class JceDecoderTest { writeJceStruct(TestSimpleJceStruct(), 10) writeCollection(listOf(listOf(1, 2, 3), listOf(1, 2, 3)), 11) }.readBytes().toUHexString(), - TestComplexJceStruct().toByteArray(TestComplexJceStruct.serializer()).toUHexString() + TestComplexNullableJceStruct().toByteArray(TestComplexNullableJceStruct.serializer()).toUHexString() ) }