From 472da8d3f60c5cf6572d23c28100e6b93a36c64f Mon Sep 17 00:00:00 2001 From: Him188 Date: Fri, 6 Mar 2020 22:05:55 +0800 Subject: [PATCH] List support --- .../io/serialization/jce/JceDecoder.kt | 51 ++++++++++++++++--- .../JceInputTest.kt | 41 +++++++++++++++ 2 files changed, 84 insertions(+), 8 deletions(-) diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/jce/JceDecoder.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/jce/JceDecoder.kt index b63bbaf42..596e5481c 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/jce/JceDecoder.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/jce/JceDecoder.kt @@ -10,6 +10,7 @@ package net.mamoe.mirai.qqandroid.io.serialization.jce import kotlinx.serialization.* +import kotlinx.serialization.builtins.AbstractDecoder import kotlinx.serialization.builtins.ByteArraySerializer import kotlinx.serialization.internal.TaggedDecoder import kotlinx.serialization.modules.SerialModule @@ -46,13 +47,29 @@ internal class JceDecoder( } // TODO: 2020/3/6 can be object - private inner class SimpleByteArrayReader : CompositeDecoder by this { + private inner class SimpleByteArrayReader : AbstractDecoder() { override fun decodeSequentially(): Boolean = true - override fun decodeByteElement(descriptor: SerialDescriptor, index: Int): Byte { - println("decodeByteElement: $index") - return jce.input.readByte().also { println("read: $it") } + + override fun endStructure(descriptor: SerialDescriptor) { + this@JceDecoder.endStructure(descriptor) } + override fun beginStructure(descriptor: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeDecoder { + this@JceDecoder.pushTag(JceTag(0, false)) + return this@JceDecoder.beginStructure(descriptor, *typeParams) + } + + override fun decodeByte(): Byte = jce.input.readByte().also { println("decodeByte: $it") } + override fun decodeShort(): Short = error("illegal access") + override fun decodeInt(): Int = error("illegal access") + override fun decodeLong(): Long = error("illegal access") + override fun decodeFloat(): Float = error("illegal access") + override fun decodeDouble(): Double = error("illegal access") + override fun decodeBoolean(): Boolean = error("illegal access") + override fun decodeChar(): Char = error("illegal access") + override fun decodeEnum(enumDescriptor: SerialDescriptor): Int = error("illegal access") + override fun decodeString(): String = error("illegal access") + override fun decodeElementIndex(descriptor: SerialDescriptor): Int { error("should not be reached") } @@ -64,23 +81,41 @@ internal class JceDecoder( } // TODO: 2020/3/6 can be object - private inner class ListReader : CompositeDecoder by this { + private inner class ListReader : AbstractDecoder() { override fun decodeSequentially(): Boolean = true override fun decodeElementIndex(descriptor: SerialDescriptor): Int = error("should not be reached") override fun endStructure(descriptor: SerialDescriptor) { - println("endStructure: ${descriptor.serialName}") + this@JceDecoder.endStructure(descriptor) } + override fun beginStructure(descriptor: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeDecoder { + this@JceDecoder.pushTag(JceTag(0, false)) + return this@JceDecoder.beginStructure(descriptor, *typeParams) + } + + override fun decodeByte(): Byte = jce.useHead { jce.readJceByteValue(it) } + override fun decodeShort(): Short = jce.useHead { jce.readJceShortValue(it) } + override fun decodeInt(): Int = jce.useHead { jce.readJceIntValue(it) } + override fun decodeLong(): Long = jce.useHead { jce.readJceLongValue(it) } + override fun decodeFloat(): Float = jce.useHead { jce.readJceFloatValue(it) } + override fun decodeDouble(): Double = jce.useHead { jce.readJceDoubleValue(it) } + override fun decodeBoolean(): Boolean = jce.useHead { jce.readJceBooleanValue(it) } + override fun decodeChar(): Char = decodeByte().toChar() + override fun decodeEnum(enumDescriptor: SerialDescriptor): Int = decodeInt() + override fun decodeString(): String = jce.useHead { jce.readJceStringValue(it) } + override fun decodeCollectionSize(descriptor: SerialDescriptor): Int { + println("decodeCollectionSize: ${descriptor.serialName}") // 不读下一个 head - return jce.currentHead.let { jce.readJceIntValue(it) }.also { println("listSize=$it") } + return jce.useHead { jce.readJceIntValue(it) }.also { println("listSize=$it") } } } override fun endStructure(descriptor: SerialDescriptor) { + println("endStructure: $descriptor") if (descriptor == ByteArraySerializer.descriptor) { jce.prepareNextHead() // list 里面没读 head - } + } else jce.prepareNextHead() // TODO ?? 测试这里 super.endStructure(descriptor) } diff --git a/mirai-core-qqandroid/src/commonTest/kotlin/net.mamoe.mirai.qqandroid.io.serialization/JceInputTest.kt b/mirai-core-qqandroid/src/commonTest/kotlin/net.mamoe.mirai.qqandroid.io.serialization/JceInputTest.kt index eed7b65e4..21e5bcd7a 100644 --- a/mirai-core-qqandroid/src/commonTest/kotlin/net.mamoe.mirai.qqandroid.io.serialization/JceInputTest.kt +++ b/mirai-core-qqandroid/src/commonTest/kotlin/net.mamoe.mirai.qqandroid.io.serialization/JceInputTest.kt @@ -40,6 +40,46 @@ internal const val ZERO_TYPE: Byte = 12 @Suppress("INVISIBLE_MEMBER") // bug internal class JceInputTest { + + @Test + fun testNestedList() { + @Serializable + data class TestSerializableClassA( + // @JceId(0) val byteArray: ByteArray = byteArrayOf(1, 2, 3), + @JceId(3) val byteArray2: List> = listOf(listOf(1, 2, 3, 4), listOf(1, 2, 3, 4)) + ) + + val input = buildPacket { + //writeJceHead(SIMPLE_LIST, 0) + //writeJceHead(BYTE, 0) + + //writeJceHead(BYTE, 0) + //byteArrayOf(1, 2, 3).let { + // writeByte(it.size.toByte()) + // writeFully(it) + //} + + writeJceHead(LIST, 3) + + writeJceHead(BYTE, 0) + writeByte(2) + listOf(listOf(1, 2, 3, 4), listOf(1, 2, 3, 4)).forEach { + writeJceHead(LIST, 0) + + writeJceHead(BYTE, 0) + writeByte(it.size.toByte()) + + it.forEach { + writeJceHead(INT, 0) + writeInt(it) + } + } + } + + assertEquals(TestSerializableClassA(), JceNew.UTF_8.load(TestSerializableClassA.serializer(), input)) + } + + @Test fun testSimpleByteArray() { @Serializable @@ -58,6 +98,7 @@ internal class JceInputTest { return true } + override fun hashCode(): Int { var result = byteArray.contentHashCode() result = 31 * result + byteArray2.hashCode()