mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-03 02:29:21 +08:00
Fix TarsInput.skipField again
This commit is contained in:
parent
2d5a37f220
commit
7edcf987ce
@ -22,6 +22,7 @@ internal class TarsInput(
|
|||||||
val input: Input, private val charset: Charset
|
val input: Input, private val charset: Charset
|
||||||
) {
|
) {
|
||||||
private var _head: TarsHead? = null
|
private var _head: TarsHead? = null
|
||||||
|
private var _nextHead: TarsHead? = null
|
||||||
|
|
||||||
val currentHead: TarsHead get() = _head ?: throw EOFException("No current TarsHead available")
|
val currentHead: TarsHead get() = _head ?: throw EOFException("No current TarsHead available")
|
||||||
val currentHeadOrNull: TarsHead? get() = _head
|
val currentHeadOrNull: TarsHead? get() = _head
|
||||||
@ -30,6 +31,19 @@ internal class TarsInput(
|
|||||||
prepareNextHead()
|
prepareNextHead()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预读取下个 [TarsHead]
|
||||||
|
*
|
||||||
|
* 注意: 应该读完 [currentHead] 的值再调用
|
||||||
|
*/
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
fun peekNextHead(): TarsHead? {
|
||||||
|
_nextHead?.let { return it }
|
||||||
|
return readNextHeadButDoNotAssignTo_Head(true).also { _nextHead = it; }.also {
|
||||||
|
println("Peek next head: $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 读取下一个 [TarsHead] 并保存. 可通过 [currentHead] 获取这个 [TarsHead].
|
* 读取下一个 [TarsHead] 并保存. 可通过 [currentHead] 获取这个 [TarsHead].
|
||||||
*
|
*
|
||||||
@ -52,7 +66,16 @@ internal class TarsInput(
|
|||||||
*/
|
*/
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
@OptIn(ExperimentalUnsignedTypes::class)
|
@OptIn(ExperimentalUnsignedTypes::class)
|
||||||
private fun readNextHeadButDoNotAssignTo_Head(): TarsHead? {
|
private fun readNextHeadButDoNotAssignTo_Head(
|
||||||
|
ignoreNextHead: Boolean = false
|
||||||
|
): TarsHead? {
|
||||||
|
if (!ignoreNextHead) {
|
||||||
|
val n = _nextHead
|
||||||
|
if (n != null) {
|
||||||
|
_nextHead = null
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
}
|
||||||
if (input.endOfInput) {
|
if (input.endOfInput) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@ -94,6 +117,25 @@ internal class TarsInput(
|
|||||||
return checkNotNull<R>(skipToHeadAndUseIfPossibleOrNull(tag, block), message)
|
return checkNotNull<R>(skipToHeadAndUseIfPossibleOrNull(tag, block), message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
fun skipToTag(tag: Int): Boolean {
|
||||||
|
while (true) {
|
||||||
|
val hd = peekNextHead() ?: return false
|
||||||
|
if (tag <= hd.tag || hd.type == 11.toByte()) {
|
||||||
|
return tag == hd.tag
|
||||||
|
}
|
||||||
|
println("Discard $tag, $hd, ${hd.size}")
|
||||||
|
input.discardExact(hd.size)
|
||||||
|
skipField(hd.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
fun readInt32(tag: Int): Int {
|
||||||
|
if (!skipToTag(tag)) return 0
|
||||||
|
return readTarsIntValue(nextHead())
|
||||||
|
}
|
||||||
|
|
||||||
tailrec fun skipToHeadOrNull(tag: Int): TarsHead? {
|
tailrec fun skipToHeadOrNull(tag: Int): TarsHead? {
|
||||||
val current: TarsHead = currentHeadOrNull ?: return null // no backing field
|
val current: TarsHead = currentHeadOrNull ?: return null // no backing field
|
||||||
|
|
||||||
@ -129,16 +171,18 @@ internal class TarsInput(
|
|||||||
Tars.STRING4 -> this.input.discardExact(this.input.readInt())
|
Tars.STRING4 -> this.input.discardExact(this.input.readInt())
|
||||||
Tars.MAP -> { // map
|
Tars.MAP -> { // map
|
||||||
TarsDecoder.structureHierarchy++
|
TarsDecoder.structureHierarchy++
|
||||||
val sizeHead = nextHead()
|
repeat(readInt32(0).also {
|
||||||
repeat(readTarsIntValue(sizeHead)) {
|
println("SIZE = $it")
|
||||||
|
} * 2) {
|
||||||
skipField(nextHead().type)
|
skipField(nextHead().type)
|
||||||
}
|
}
|
||||||
TarsDecoder.structureHierarchy--
|
TarsDecoder.structureHierarchy--
|
||||||
}
|
}
|
||||||
Tars.LIST -> { // list
|
Tars.LIST -> { // list
|
||||||
TarsDecoder.structureHierarchy++
|
TarsDecoder.structureHierarchy++
|
||||||
val sizeHead = nextHead()
|
repeat(readInt32(0).also {
|
||||||
repeat(readTarsIntValue(sizeHead) * 2) {
|
println("SIZE = $it")
|
||||||
|
}) {
|
||||||
skipField(nextHead().type)
|
skipField(nextHead().type)
|
||||||
}
|
}
|
||||||
TarsDecoder.structureHierarchy--
|
TarsDecoder.structureHierarchy--
|
||||||
@ -161,7 +205,7 @@ internal class TarsInput(
|
|||||||
Tars.SIMPLE_LIST -> {
|
Tars.SIMPLE_LIST -> {
|
||||||
TarsDecoder.structureHierarchy++
|
TarsDecoder.structureHierarchy++
|
||||||
var head = nextHead()
|
var head = nextHead()
|
||||||
check(head.type == Tars.BYTE) { "bad simple list element type: " + head.type }
|
check(head.type == Tars.BYTE) { "bad simple list element type: " + head.type + ", $head" }
|
||||||
check(head.tag == 0) { "simple list element tag must be 0, but was ${head.tag}" }
|
check(head.tag == 0) { "simple list element tag must be 0, but was ${head.tag}" }
|
||||||
|
|
||||||
head = nextHead()
|
head = nextHead()
|
||||||
@ -176,7 +220,12 @@ internal class TarsInput(
|
|||||||
// region readers
|
// region readers
|
||||||
fun readTarsIntValue(head: TarsHead): Int {
|
fun readTarsIntValue(head: TarsHead): Int {
|
||||||
//println("readTarsIntValue: $head")
|
//println("readTarsIntValue: $head")
|
||||||
return when (head.type) {
|
return readTarsIntValue(head.type, head)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
fun readTarsIntValue(type: Byte, head: Any = type): Int {
|
||||||
|
return when (type) {
|
||||||
Tars.ZERO_TYPE -> 0
|
Tars.ZERO_TYPE -> 0
|
||||||
Tars.BYTE -> input.readByte().toInt()
|
Tars.BYTE -> input.readByte().toInt()
|
||||||
Tars.SHORT -> input.readShort().toInt()
|
Tars.SHORT -> input.readShort().toInt()
|
||||||
|
@ -81,6 +81,16 @@ internal class TarsHead(private val value: Long) {
|
|||||||
|
|
||||||
val tag: Int get() = (value ushr 32).toInt()
|
val tag: Int get() = (value ushr 32).toInt()
|
||||||
val type: Byte get() = value.toUInt().toByte()
|
val type: Byte get() = value.toUInt().toByte()
|
||||||
|
val size: Int
|
||||||
|
get() {
|
||||||
|
if (tag < 15) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if (tag < 256) {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
error("tag is too large: $tag")
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "TarsHead(tag=$tag, type=$type(${findTarsTypeName(type)}))"
|
return "TarsHead(tag=$tag, type=$type(${findTarsTypeName(type)}))"
|
||||||
|
Loading…
Reference in New Issue
Block a user