mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-12 14:00:12 +08:00
Throws EOFException rather than IllegalStateException
This commit is contained in:
parent
115ccec9ed
commit
24983d8bbe
@ -45,28 +45,28 @@ private class JceDecoder(
|
||||
}
|
||||
|
||||
override fun decodeTaggedInt(tag: JceTag): Int =
|
||||
jce.skipToTagAndUseIfPossibleOrFail(tag.id) { jce.readJceIntValue(it) }
|
||||
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceIntValue(it) }
|
||||
|
||||
override fun decodeTaggedByte(tag: JceTag): Byte =
|
||||
jce.skipToTagAndUseIfPossibleOrFail(tag.id) { jce.readJceByteValue(it) }
|
||||
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceByteValue(it) }
|
||||
|
||||
override fun decodeTaggedBoolean(tag: JceTag): Boolean =
|
||||
jce.skipToTagAndUseIfPossibleOrFail(tag.id) { jce.readJceBooleanValue(it) }
|
||||
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceBooleanValue(it) }
|
||||
|
||||
override fun decodeTaggedFloat(tag: JceTag): Float =
|
||||
jce.skipToTagAndUseIfPossibleOrFail(tag.id) { jce.readJceFloatValue(it) }
|
||||
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceFloatValue(it) }
|
||||
|
||||
override fun decodeTaggedDouble(tag: JceTag): Double =
|
||||
jce.skipToTagAndUseIfPossibleOrFail(tag.id) { jce.readJceDoubleValue(it) }
|
||||
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceDoubleValue(it) }
|
||||
|
||||
override fun decodeTaggedShort(tag: JceTag): Short =
|
||||
jce.skipToTagAndUseIfPossibleOrFail(tag.id) { jce.readJceShortValue(it) }
|
||||
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceShortValue(it) }
|
||||
|
||||
override fun decodeTaggedLong(tag: JceTag): Long =
|
||||
jce.skipToTagAndUseIfPossibleOrFail(tag.id) { jce.readJceLongValue(it) }
|
||||
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceLongValue(it) }
|
||||
|
||||
override fun decodeTaggedString(tag: JceTag): String =
|
||||
jce.skipToTagAndUseIfPossibleOrFail(tag.id) { jce.readJceStringValue(it) }
|
||||
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceStringValue(it) }
|
||||
|
||||
override fun decodeTaggedEnum(tag: JceTag, enumDescription: SerialDescriptor): Int {
|
||||
return super.decodeTaggedEnum(tag, enumDescription)
|
||||
|
@ -23,7 +23,7 @@ class JceInput(
|
||||
) {
|
||||
private var _head: JceHead? = null
|
||||
|
||||
val currentHead: JceHead get() = _head ?: error("No current JceHead available")
|
||||
val currentHead: JceHead get() = _head ?: throw EOFException("No current JceHead available")
|
||||
val currentHeadOrNull: JceHead? get() = _head
|
||||
|
||||
init {
|
||||
@ -40,7 +40,9 @@ class JceInput(
|
||||
}
|
||||
|
||||
fun nextHead(): JceHead {
|
||||
check(prepareNextHead()) { "No more JceHead available" }
|
||||
if (!prepareNextHead()) {
|
||||
throw EOFException("No more JceHead available")
|
||||
}
|
||||
return currentHead
|
||||
}
|
||||
|
||||
@ -51,13 +53,13 @@ class JceInput(
|
||||
@Suppress("FunctionName")
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
private fun readNextHeadButDoNotAssignTo_Head(): JceHead? {
|
||||
if (input.endOfInput) {
|
||||
return null
|
||||
}
|
||||
val var2 = input.readUByte()
|
||||
val type = var2 and 15u
|
||||
var tag = var2.toUInt() shr 4
|
||||
if (tag == 15u) {
|
||||
if (input.endOfInput) {
|
||||
return null
|
||||
}
|
||||
tag = input.readUByte().toUInt()
|
||||
}
|
||||
return JceHead(
|
||||
@ -77,19 +79,19 @@ class JceInput(
|
||||
/**
|
||||
* 跳过 [JceHead] 和对应的数据值, 直到找到 [tag], 否则返回 `null`
|
||||
*/
|
||||
inline fun <R> skipToTagAndUseIfPossibleOrNull(tag: Int, crossinline block: (JceHead) -> R): R? {
|
||||
inline fun <R> skipToHeadAndUseIfPossibleOrNull(tag: Int, crossinline block: (JceHead) -> R): R? {
|
||||
return skipToHeadOrNull(tag)?.let(block).also { prepareNextHead() }
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳过 [JceHead] 和对应的数据值, 直到找到 [tag], 否则抛出异常
|
||||
*/
|
||||
inline fun <R : Any> skipToTagAndUseIfPossibleOrFail(
|
||||
inline fun <R : Any> skipToHeadAndUseIfPossibleOrFail(
|
||||
tag: Int,
|
||||
crossinline message: () -> String = { "tag not found: $tag" },
|
||||
crossinline block: (JceHead) -> R
|
||||
): R {
|
||||
return checkNotNull<R>(skipToTagAndUseIfPossibleOrNull(tag, block), message)
|
||||
return checkNotNull<R>(skipToHeadAndUseIfPossibleOrNull(tag, block), message)
|
||||
}
|
||||
|
||||
tailrec fun skipToHeadOrNull(tag: Int): JceHead? {
|
||||
@ -125,14 +127,14 @@ class JceInput(
|
||||
Jce.STRING1 -> this.input.discardExact(this.input.readUByte().toInt())
|
||||
Jce.STRING4 -> this.input.discardExact(this.input.readInt())
|
||||
Jce.MAP -> { // map
|
||||
repeat(skipToTagAndUseIfPossibleOrFail(0) {
|
||||
repeat(skipToHeadAndUseIfPossibleOrFail(0) {
|
||||
readJceIntValue(it)
|
||||
} * 2) {
|
||||
useHead { skipField(it.type) }
|
||||
}
|
||||
}
|
||||
Jce.LIST -> { // list
|
||||
repeat(skipToTagAndUseIfPossibleOrFail(0) {
|
||||
repeat(skipToHeadAndUseIfPossibleOrFail(0) {
|
||||
readJceIntValue(it)
|
||||
}) {
|
||||
useHead { skipField(it.type) }
|
||||
@ -155,7 +157,7 @@ class JceInput(
|
||||
val head = nextHead()
|
||||
check(head.type.toInt() == 0) { "skipField with invalid type, type value: " + type + ", " + head.type }
|
||||
this.input.discardExact(
|
||||
skipToTagAndUseIfPossibleOrFail(0) {
|
||||
skipToHeadAndUseIfPossibleOrFail(0) {
|
||||
readJceIntValue(it)
|
||||
}
|
||||
)
|
||||
@ -232,6 +234,6 @@ class JceInput(
|
||||
}
|
||||
|
||||
fun readJceBooleanValue(head: JceHead): Boolean {
|
||||
return readJceByteValue(head) == 0.toByte()
|
||||
return readJceByteValue(head) == 1.toByte()
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
package net.mamoe.mirai.qqandroid.io.serialization.jce
|
||||
|
||||
import io.ktor.utils.io.core.Output
|
||||
import kotlinx.serialization.SerialInfo
|
||||
import net.mamoe.mirai.qqandroid.io.serialization.Jce
|
||||
|
||||
@ -24,12 +25,27 @@ annotation class JceId(val id: Int)
|
||||
*
|
||||
* 保留这个结构, 为将来增加功能的兼容性.
|
||||
*/
|
||||
@PublishedApi
|
||||
internal data class JceTag(
|
||||
val id: Int,
|
||||
val isNullable: Boolean
|
||||
)
|
||||
|
||||
|
||||
@PublishedApi
|
||||
internal fun Output.writeJceHead(type: Byte, tag: Int) {
|
||||
if (tag < 15) {
|
||||
writeByte(((tag shl 4) or type.toInt()).toByte())
|
||||
return
|
||||
}
|
||||
if (tag < 256) {
|
||||
writeByte((type.toInt() or 0xF0).toByte())
|
||||
writeByte(tag.toByte())
|
||||
return
|
||||
}
|
||||
error("tag is too large: $tag")
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
inline class JceHead(private val value: Long) {
|
||||
constructor(tag: Int, type: Byte) : this(tag.toLong().shl(32) or type.toLong())
|
||||
|
Loading…
Reference in New Issue
Block a user