mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-05 07:30:09 +08:00
Fix Map entry tags, remove debugging logs
This commit is contained in:
parent
ce7af37ef4
commit
c69cb6f3de
@ -15,7 +15,6 @@ import kotlinx.serialization.*
|
||||
import kotlinx.serialization.builtins.AbstractDecoder
|
||||
import kotlinx.serialization.internal.TaggedDecoder
|
||||
import kotlinx.serialization.modules.SerialModule
|
||||
import net.mamoe.mirai.qqandroid.io.serialization.Jce
|
||||
|
||||
|
||||
@OptIn(InternalSerializationApi::class) // 将来 kotlinx 修改后再复制过来 mirai.
|
||||
@ -30,16 +29,13 @@ internal class JceDecoder(
|
||||
|
||||
val id = annotations.filterIsInstance<JceId>().single().id
|
||||
// ?: error("cannot find @JceId or @ProtoId for ${this.getElementName(index)} in ${this.serialName}")
|
||||
println("getTag: ${this.getElementName(index)}=$id")
|
||||
//println("getTag: ${this.getElementName(index)}=$id")
|
||||
|
||||
return JceTag(
|
||||
id,
|
||||
this.getElementDescriptor(index).isNullable
|
||||
)
|
||||
return JceTagCommon(id)
|
||||
}
|
||||
|
||||
private fun SerialDescriptor.getJceTagId(index: Int): Int {
|
||||
println("getTag: ${getElementName(index)}")
|
||||
//println("getTag: ${getElementName(index)}")
|
||||
return getElementAnnotations(index).filterIsInstance<JceId>().singleOrNull()?.id
|
||||
?: error("missing @JceId for ${getElementName(index)} in ${this.serialName}")
|
||||
}
|
||||
@ -54,11 +50,11 @@ internal class JceDecoder(
|
||||
}
|
||||
|
||||
override fun beginStructure(descriptor: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeDecoder {
|
||||
this@JceDecoder.pushTag(JceTag(0, false))
|
||||
this@JceDecoder.pushTag(JceTagListElement)
|
||||
return this@JceDecoder.beginStructure(descriptor, *typeParams)
|
||||
}
|
||||
|
||||
override fun decodeByte(): Byte = jce.input.readByte().also { println("decodeByte: $it") }
|
||||
override fun decodeByte(): Byte = jce.input.readByte()
|
||||
override fun decodeShort(): Short = error("illegal access")
|
||||
override fun decodeInt(): Int = error("illegal access")
|
||||
override fun decodeLong(): Long = error("illegal access")
|
||||
@ -75,7 +71,7 @@ internal class JceDecoder(
|
||||
|
||||
override fun decodeCollectionSize(descriptor: SerialDescriptor): Int {
|
||||
// 不要读下一个 head
|
||||
return jce.currentHead.let { jce.readJceIntValue(it) }.also { println("simpleListSize=$it") }
|
||||
return jce.currentHead.let { jce.readJceIntValue(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,7 +85,8 @@ internal class JceDecoder(
|
||||
}
|
||||
|
||||
override fun beginStructure(descriptor: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeDecoder {
|
||||
this@JceDecoder.pushTag(JceTag(0, false))
|
||||
this@JceDecoder.pushTag(JceTagListElement)
|
||||
|
||||
return this@JceDecoder.beginStructure(descriptor, *typeParams)
|
||||
}
|
||||
|
||||
@ -105,9 +102,9 @@ internal class JceDecoder(
|
||||
override fun decodeString(): String = jce.useHead { jce.readJceStringValue(it) }
|
||||
|
||||
override fun decodeCollectionSize(descriptor: SerialDescriptor): Int {
|
||||
println("decodeCollectionSize: ${descriptor.serialName}")
|
||||
//println("decodeCollectionSize: ${descriptor.serialName}")
|
||||
// 不读下一个 head
|
||||
return jce.useHead { jce.readJceIntValue(it) }.also { println("listSize=$it") }
|
||||
return jce.useHead { jce.readJceIntValue(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,14 +113,16 @@ internal class JceDecoder(
|
||||
|
||||
private inner class MapReaderImpl : AbstractDecoder() {
|
||||
override fun decodeSequentially(): Boolean = true
|
||||
override fun decodeElementIndex(descriptor: SerialDescriptor): Int = error("should not be reached")
|
||||
override fun decodeElementIndex(descriptor: SerialDescriptor): Int = error("stub")
|
||||
|
||||
override fun endStructure(descriptor: SerialDescriptor) {
|
||||
this@JceDecoder.endStructure(descriptor)
|
||||
}
|
||||
|
||||
private var state: Boolean = true
|
||||
|
||||
override fun beginStructure(descriptor: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeDecoder {
|
||||
this@JceDecoder.pushTag(JceTag(if (state) 0 else 1, false))
|
||||
this@JceDecoder.pushTag(if (jce.currentHead.tag == 0) JceTagMapEntryKey else JceTagMapEntryValue)
|
||||
state = !state
|
||||
return this@JceDecoder.beginStructure(descriptor, *typeParams)
|
||||
}
|
||||
@ -134,21 +133,22 @@ internal class JceDecoder(
|
||||
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 in MapReader: ${descriptor.serialName}")
|
||||
//println("decodeCollectionSize in MapReader: ${descriptor.serialName}")
|
||||
// 不读下一个 head
|
||||
return jce.useHead { jce.readJceIntValue(it) }.also { println("listSize=$it") }
|
||||
return jce.useHead { jce.readJceIntValue(it) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun endStructure(descriptor: SerialDescriptor) {
|
||||
println("endStructure: $descriptor")
|
||||
//println("endStructure: $descriptor")
|
||||
if (currentTagOrNull?.isSimpleByteArray == true) {
|
||||
jce.prepareNextHead() // read to next head
|
||||
}
|
||||
@ -160,10 +160,10 @@ internal class JceDecoder(
|
||||
val currentHead = jce.currentHeadOrNull ?: return
|
||||
if (currentHead.type == Jce.STRUCT_END) {
|
||||
jce.prepareNextHead()
|
||||
println("current end")
|
||||
//println("current end")
|
||||
break
|
||||
}
|
||||
println("current $currentHead")
|
||||
//println("current $currentHead")
|
||||
jce.skipField(currentHead.type)
|
||||
jce.prepareNextHead()
|
||||
}
|
||||
@ -174,24 +174,24 @@ internal class JceDecoder(
|
||||
}
|
||||
|
||||
override fun beginStructure(descriptor: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeDecoder {
|
||||
println()
|
||||
println("beginStructure: ${descriptor.serialName}")
|
||||
//println()
|
||||
//println("beginStructure: ${descriptor.serialName}")
|
||||
return when (descriptor.kind) {
|
||||
is PrimitiveKind -> this@JceDecoder
|
||||
|
||||
StructureKind.MAP -> {
|
||||
println("!! MAP")
|
||||
//println("!! MAP")
|
||||
return jce.skipToHeadAndUseIfPossibleOrFail(popTag().id) {
|
||||
it.checkType(Jce.MAP)
|
||||
MapReader
|
||||
}
|
||||
}
|
||||
StructureKind.LIST -> {
|
||||
println("!! ByteArray")
|
||||
println("decoderTag: $currentTagOrNull")
|
||||
println("jceHead: " + jce.currentHeadOrNull)
|
||||
//println("!! ByteArray")
|
||||
//println("decoderTag: $currentTagOrNull")
|
||||
//println("jceHead: " + jce.currentHeadOrNull)
|
||||
return jce.skipToHeadAndUseIfPossibleOrFail(currentTag.id) {
|
||||
println("listHead: $it")
|
||||
//println("listHead: $it")
|
||||
when (it.type) {
|
||||
Jce.SIMPLE_LIST -> {
|
||||
currentTag.isSimpleByteArray = true
|
||||
@ -204,11 +204,11 @@ internal class JceDecoder(
|
||||
}
|
||||
}
|
||||
StructureKind.CLASS -> {
|
||||
val currentTag = currentTagOrNull ?: return this@JceDecoder
|
||||
currentTagOrNull ?: return this@JceDecoder // outermost
|
||||
|
||||
println("!! CLASS")
|
||||
println("decoderTag: $currentTag")
|
||||
println("jceHead: " + jce.currentHeadOrNull)
|
||||
//println("!! CLASS")
|
||||
//println("decoderTag: $currentTag")
|
||||
//println("jceHead: " + jce.currentHeadOrNull)
|
||||
return jce.skipToHeadAndUseIfPossibleOrFail(popTag().id) { jceHead ->
|
||||
jceHead.checkType(Jce.STRUCT_BEGIN)
|
||||
|
||||
@ -227,14 +227,6 @@ internal class JceDecoder(
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T> decodeSerializableValue(deserializer: DeserializationStrategy<T>): T {
|
||||
println(
|
||||
"decodeSerializableValue: ${deserializer.descriptor.toString().substringBefore('(')
|
||||
.substringAfterLast('.')}"
|
||||
)
|
||||
return super.decodeSerializableValue(deserializer)
|
||||
}
|
||||
|
||||
override fun decodeSequentially(): Boolean = false
|
||||
override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
|
||||
val jceHead = jce.currentHeadOrNull ?: return CompositeDecoder.READ_DONE
|
||||
@ -252,16 +244,6 @@ internal class JceDecoder(
|
||||
return CompositeDecoder.READ_DONE // optional support
|
||||
}
|
||||
|
||||
override fun decodeTaggedNull(tag: JceTag): Nothing? {
|
||||
println("decodeTaggedNull")
|
||||
return super.decodeTaggedNull(tag)
|
||||
}
|
||||
|
||||
override fun decodeTaggedValue(tag: JceTag): Any {
|
||||
println("decodeTaggedValue")
|
||||
return super.decodeTaggedValue(tag)
|
||||
}
|
||||
|
||||
override fun decodeTaggedInt(tag: JceTag): Int =
|
||||
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceIntValue(it) }
|
||||
|
||||
|
@ -166,7 +166,7 @@ internal class JceInput(
|
||||
|
||||
// region readers
|
||||
fun readJceIntValue(head: JceHead): Int {
|
||||
println("readJceIntValue: $head")
|
||||
//println("readJceIntValue: $head")
|
||||
return when (head.type) {
|
||||
Jce.ZERO_TYPE -> 0
|
||||
Jce.BYTE -> input.readByte().toInt()
|
||||
@ -197,7 +197,7 @@ internal class JceInput(
|
||||
}
|
||||
|
||||
fun readJceByteValue(head: JceHead): Byte {
|
||||
println("readJceByteValue: $head")
|
||||
//println("readJceByteValue: $head")
|
||||
return when (head.type) {
|
||||
Jce.ZERO_TYPE -> 0
|
||||
Jce.BYTE -> input.readByte()
|
||||
@ -215,6 +215,7 @@ internal class JceInput(
|
||||
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
fun readJceStringValue(head: JceHead): String {
|
||||
//println("readJceStringValue: $head")
|
||||
return when (head.type) {
|
||||
Jce.STRING1 -> input.readString(input.readUByte().toInt(), charset = charset.kotlinCharset)
|
||||
Jce.STRING4 -> input.readString(
|
||||
|
@ -28,41 +28,33 @@ annotation class JceId(val id: Int)
|
||||
@PublishedApi
|
||||
internal abstract class JceTag {
|
||||
abstract val id: Int
|
||||
abstract val isNullable: Boolean
|
||||
|
||||
internal var isSimpleByteArray: Boolean = false
|
||||
}
|
||||
|
||||
internal sealed class JceTagListElement(
|
||||
override val isNullable: Boolean
|
||||
) : JceTag(){
|
||||
internal object JceTagListElement : JceTag() {
|
||||
override val id: Int get() = 0
|
||||
|
||||
object Nullable : JceTagListElement(true)
|
||||
object NotNull : JceTagListElement(false)
|
||||
override fun toString(): String {
|
||||
return "JceTagListElement"
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class JceTagMapEntryKey(
|
||||
override val isNullable: Boolean
|
||||
) : JceTag(){
|
||||
internal object JceTagMapEntryKey : JceTag() {
|
||||
override val id: Int get() = 0
|
||||
|
||||
object Nullable : JceTagMapEntryKey(true)
|
||||
object NotNull : JceTagMapEntryKey(false)
|
||||
override fun toString(): String {
|
||||
return "JceTagMapEntryKey"
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class JceTagMapEntryValue(
|
||||
override val isNullable: Boolean
|
||||
) : JceTag() {
|
||||
internal object JceTagMapEntryValue : JceTag() {
|
||||
override val id: Int get() = 1
|
||||
|
||||
object Nullable : JceTagMapEntryValue(true)
|
||||
object NotNull : JceTagMapEntryValue(false)
|
||||
override fun toString(): String {
|
||||
return "JceTagMapEntryValue"
|
||||
}
|
||||
}
|
||||
|
||||
internal data class JceTagCommon(
|
||||
override val id: Int,
|
||||
override val isNullable: Boolean
|
||||
override val id: Int
|
||||
) : JceTag()
|
||||
|
||||
fun JceHead.checkType(type: Byte) {
|
||||
|
@ -3,6 +3,7 @@
|
||||
package net.mamoe.mirai.qqandroid.io.serialization
|
||||
|
||||
import kotlinx.io.core.buildPacket
|
||||
import kotlinx.io.core.toByteArray
|
||||
import kotlinx.io.core.writeFully
|
||||
import kotlinx.serialization.MissingFieldException
|
||||
import kotlinx.serialization.Serializable
|
||||
@ -271,8 +272,13 @@ internal class JceInputTest {
|
||||
fun testMapStringByteArray() {
|
||||
@Serializable
|
||||
data class TestSerializableClassA(
|
||||
@JceId(0) val byteArray: Map<String, ByteArray>
|
||||
)
|
||||
@JceId(0) val map: Map<String, ByteArray>
|
||||
) {
|
||||
override fun toString(): String {
|
||||
@Suppress("EXPERIMENTAL_API_USAGE")
|
||||
return map.entries.joinToString { "${it.key}=${it.value.contentToString()}" }
|
||||
}
|
||||
}
|
||||
|
||||
val input = buildPacket {
|
||||
writeJceHead(MAP, 0)
|
||||
@ -284,18 +290,20 @@ internal class JceInputTest {
|
||||
it.forEach { (key, value) ->
|
||||
writeJceHead(STRING1, 0)
|
||||
writeByte(key.length.toByte())
|
||||
writeStringUtf8(key)
|
||||
writeFully(key.toByteArray())
|
||||
|
||||
writeJceHead(SIMPLE_LIST, 1)
|
||||
writeJceHead(BYTE, 0)
|
||||
writeJceHead(INT, 0)
|
||||
writeInt(value.size)
|
||||
writeFully(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
TestSerializableClassA(mapOf("str1" to byteArrayOf(2, 3, 4), "str2" to byteArrayOf(2, 3, 4))),
|
||||
Jce.UTF_8.load(TestSerializableClassA.serializer(), input)
|
||||
TestSerializableClassA(mapOf("str1" to byteArrayOf(2, 3, 4), "str2" to byteArrayOf(2, 3, 4))).toString(),
|
||||
Jce.UTF_8.load(TestSerializableClassA.serializer(), input).toString()
|
||||
)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user