Commit afa2cc70 authored by Him188's avatar Him188

Fix deserializing nested struct in map

parent 9d206d1a
...@@ -308,7 +308,10 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo ...@@ -308,7 +308,10 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
input: JceInput input: JceInput
) : JceDecoder(input) { ) : JceDecoder(input) {
override fun endStructure(desc: SerialDescriptor) { override fun endStructure(desc: SerialDescriptor) {
input.readHeadOrNull() // STRUCT_END while (input.peakHead().type != STRUCT_END) {
input.readHead()
}
input.readHead()
} }
} }
...@@ -320,7 +323,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo ...@@ -320,7 +323,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
internal val input: JceInput internal val input: JceInput
) : TaggedDecoder<Int>() { ) : TaggedDecoder<Int>() {
override fun SerialDescriptor.getTag(index: Int): Int { override fun SerialDescriptor.getTag(index: Int): Int {
return getSerialId(this, index) ?: error("cannot find tag") return getSerialId(this, index) ?: error("cannot find tag with index $index")
} }
override fun decodeTaggedByte(tag: Int): Byte = input.readByte(tag) override fun decodeTaggedByte(tag: Int): Byte = input.readByte(tag)
...@@ -387,21 +390,6 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo ...@@ -387,21 +390,6 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
} }
} }
if (desc.kind == StructureKind.CLASS || desc.kind == UnionKind.OBJECT) {
val tag = currentTagOrNull
if (tag != null) {
@Suppress("SENSELESS_COMPARISON") // 推断 bug
if (input.skipToTagOrNull(tag) {
popTag()
return JceStructReader(input)
} == null && desc.isNullable) {
return NullReader(this.input)
}
}
return this // top-level
}
return super.beginStructure(desc, *typeParams) return super.beginStructure(desc, *typeParams)
} }
...@@ -419,7 +407,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo ...@@ -419,7 +407,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun <T : Any> decodeNullableSerializableValue(deserializer: DeserializationStrategy<T?>): T? { override fun <T : Any> decodeNullableSerializableValue(deserializer: DeserializationStrategy<T?>): T? {
// println("decodeNullableSerializableValue: ${deserializer.getClassName()}") println("decodeNullableSerializableValue: ${deserializer::class.qualifiedName}")
if (deserializer is NullReader) { if (deserializer is NullReader) {
return null return null
} }
...@@ -445,7 +433,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo ...@@ -445,7 +433,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
return if (isTagOptional(tag)) input.readByteArrayOrNull(tag)?.toMutableList() as? T return if (isTagOptional(tag)) input.readByteArrayOrNull(tag)?.toMutableList() as? T
else input.readByteArray(tag).toMutableList() as T else input.readByteArray(tag).toMutableList() as T
} }
val tag = popTag() val tag = currentTag
// println(tag) // println(tag)
@Suppress("SENSELESS_COMPARISON") // false positive @Suppress("SENSELESS_COMPARISON") // false positive
if (input.skipToTagOrNull(tag) { if (input.skipToTagOrNull(tag) {
...@@ -461,6 +449,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo ...@@ -461,6 +449,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
val tag = popTag() val tag = popTag()
@Suppress("SENSELESS_COMPARISON") @Suppress("SENSELESS_COMPARISON")
if (input.skipToTagOrNull(tag) { if (input.skipToTagOrNull(tag) {
check(it.type == MAP) { "type mismatch: ${it.type}" }
// 将 mapOf(k1 to v1, k2 to v2, ...) 转换为 listOf(k1, v1, k2, v2, ...) 以便于写入. // 将 mapOf(k1 to v1, k2 to v2, ...) 转换为 listOf(k1, v1, k2, v2, ...) 以便于写入.
val serializer = (deserializer as MapLikeSerializer<Any?, Any?, T, *>) val serializer = (deserializer as MapLikeSerializer<Any?, Any?, T, *>)
val mapEntrySerial = MapEntrySerializer(serializer.keySerializer, serializer.valueSerializer) val mapEntrySerial = MapEntrySerializer(serializer.keySerializer, serializer.valueSerializer)
...@@ -474,7 +463,24 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo ...@@ -474,7 +463,24 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
error("UNREACHABLE CODE") error("UNREACHABLE CODE")
} }
} }
val tag = currentTagOrNull ?: return deserializer.deserialize(this)
if (deserializer.descriptor.kind == StructureKind.CLASS || deserializer.descriptor.kind == UnionKind.OBJECT) {
val tag = currentTagOrNull
if (tag != null) {
@Suppress("SENSELESS_COMPARISON") // 推断 bug
if (input.skipToTagOrNull(tag) {
check(it.type == STRUCT_BEGIN) { "type mismatch: ${it.type}" }
//popTag()
return deserializer.deserialize(JceStructReader(input))
} == null && isTagOptional(tag)) {
return null
} else error("cannot find tag $tag")
}
return deserializer.deserialize(JceDecoder(this.input))
}
val tag = currentTagOrNull ?: return deserializer.deserialize(JceDecoder(this.input))
return if (this.decodeTaggedNotNullMark(tag)) { return if (this.decodeTaggedNotNullMark(tag)) {
deserializer.deserialize(this) deserializer.deserialize(this)
} else { } else {
...@@ -486,7 +492,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo ...@@ -486,7 +492,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun <T> decodeSerializableValue(deserializer: DeserializationStrategy<T>): T { override fun <T> decodeSerializableValue(deserializer: DeserializationStrategy<T>): T {
return decodeNullableSerializableValue(deserializer as DeserializationStrategy<Any?>) as? T return decodeNullableSerializableValue(deserializer as DeserializationStrategy<Any?>) as? T
?: error("value with tag $currentTagOrNull is not optional but cannot find") ?: error("value with tag $currentTagOrNull(by ${deserializer.getClassName()}) is not optional but cannot find")
} }
} }
...@@ -738,7 +744,8 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo ...@@ -738,7 +744,8 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
internal const val STRUCT_END: Byte = 11 internal const val STRUCT_END: Byte = 11
internal const val ZERO_TYPE: Byte = 12 internal const val ZERO_TYPE: Byte = 12
private fun Any?.getClassName(): String = (if (this == null) Unit::class else this::class).simpleName ?: "<unnamed class>" private fun Any?.getClassName(): String =
(if (this == null) Unit::class else this::class).qualifiedName?.split(".")?.takeLast(2)?.joinToString(".") ?: "<unnamed class>"
} }
fun <T> dumpAsPacket(serializer: SerializationStrategy<T>, obj: T): ByteReadPacket { fun <T> dumpAsPacket(serializer: SerializationStrategy<T>, obj: T): ByteReadPacket {
......
...@@ -37,7 +37,7 @@ internal class GetFriendListResp( ...@@ -37,7 +37,7 @@ internal class GetFriendListResp(
@SerialId(4) val getfriendCount: Short, @SerialId(4) val getfriendCount: Short,
@SerialId(5) val totoalFriendCount: Short, @SerialId(5) val totoalFriendCount: Short,
@SerialId(6) val friendCount: Short, @SerialId(6) val friendCount: Short,
@SerialId(7) val vecFriendInfo: List<FriendInfo>, @SerialId(7) val vecFriendInfo: List<FriendInfo>? = null,
@SerialId(8) val groupid: Byte? = null, @SerialId(8) val groupid: Byte? = null,
@SerialId(9) val ifGetGroupInfo: Byte, @SerialId(9) val ifGetGroupInfo: Byte,
@SerialId(10) val groupstartIndex: Byte? = null, @SerialId(10) val groupstartIndex: Byte? = null,
...@@ -67,7 +67,7 @@ internal class FriendListSubSrvRspCode( ...@@ -67,7 +67,7 @@ internal class FriendListSubSrvRspCode(
@Serializable @Serializable
internal class FriendInfo( internal class FriendInfo(
@SerialId(0) val friendUin: Long, @SerialId(0) val friendUin: Long? = 0,
@SerialId(1) val groupId: Byte, @SerialId(1) val groupId: Byte,
@SerialId(2) val faceId: Short, @SerialId(2) val faceId: Short,
@SerialId(3) val remark: String = "", @SerialId(3) val remark: String = "",
......
...@@ -102,10 +102,10 @@ abstract class BotImpl<N : BotNetworkHandler> constructor( ...@@ -102,10 +102,10 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
try { try {
return _network.login() return _network.login()
} catch (e: Exception){ } catch (e: Exception){
e.logStacktrace("Exception when login") _network.dispose(e)
} }
delay(3000)
logger.warning("Login failed. Retrying in 3s...") logger.warning("Login failed. Retrying in 3s...")
delay(3000)
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment