Skip to content

Commit

Permalink
Fix shadowed struct elements
Browse files Browse the repository at this point in the history
  • Loading branch information
Him188 committed Mar 19, 2020
1 parent 4c6e427 commit 948658c
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,9 @@ internal class JceDecoder(

companion object {
@Suppress("MemberVisibilityCanBePrivate")
val debuggingMode: Boolean by lazy { false }
var debuggingMode: Boolean = false

private var structureHierarchy: Int = 0
var structureHierarchy: Int = 0

inline fun println(value: () -> String) {
if (debuggingMode) {
Expand Down Expand Up @@ -258,7 +258,10 @@ internal class JceDecoder(

override fun decodeSequentially(): Boolean = false
override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
var jceHead = jce.currentHeadOrNull ?: return CompositeDecoder.READ_DONE
var jceHead = jce.currentHeadOrNull ?: kotlin.run {
println("decodeElementIndex: currentHead == null")
return CompositeDecoder.READ_DONE
}

println { "decodeElementIndex: ${jce.currentHead}" }
while (!jce.input.endOfInput) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,62 +116,69 @@ internal class JceInput(

@OptIn(ExperimentalUnsignedTypes::class)
@PublishedApi
internal fun skipField(type: Byte): Unit = when (type) {
Jce.BYTE -> this.input.discardExact(1)
Jce.SHORT -> this.input.discardExact(2)
Jce.INT -> this.input.discardExact(4)
Jce.LONG -> this.input.discardExact(8)
Jce.FLOAT -> this.input.discardExact(4)
Jce.DOUBLE -> this.input.discardExact(8)
Jce.STRING1 -> this.input.discardExact(this.input.readUByte().toInt())
Jce.STRING4 -> this.input.discardExact(this.input.readInt())
Jce.MAP -> { // map
//println("skip map!")
nextHead()
repeat(skipToHeadAndUseIfPossibleOrFail(0, message = { "tag 0 not found when skipping map" }) {
readJceIntValue(it)
} * 2) {
val currentHead = currentHead
prepareNextHead()
skipField(currentHead.type)
internal fun skipField(type: Byte): Unit {
JceDecoder.println { "skipping ${JceHead.findJceTypeName(type)}" }
when (type) {
Jce.BYTE -> this.input.discardExact(1)
Jce.SHORT -> this.input.discardExact(2)
Jce.INT -> println("readInt=" + this.input.readInt())
Jce.LONG -> this.input.discardExact(8)
Jce.FLOAT -> this.input.discardExact(4)
Jce.DOUBLE -> this.input.discardExact(8)
Jce.STRING1 -> this.input.discardExact(this.input.readUByte().toInt())
Jce.STRING4 -> this.input.discardExact(this.input.readInt())
Jce.MAP -> { // map
JceDecoder.structureHierarchy++
var count: Int = 0
nextHead() // avoid shadowing, don't remove
repeat(skipToHeadAndUseIfPossibleOrFail(0, message = { "tag 0 not found when skipping map" }) {
readJceIntValue(it).also { count = it * 2 }
} * 2) {
skipField(currentHead.type)
if (it != count - 1) { // don't read last head
nextHead()
}
}
JceDecoder.structureHierarchy--
}
}
Jce.LIST -> { // list
JceDecoder.println {"skip list!"}
nextHead()
repeat(skipToHeadAndUseIfPossibleOrFail(0, message = { "tag 0 not found when skipping list" }) {
readJceIntValue(it)
}) {
val currentHead = currentHead
prepareNextHead()
skipField(currentHead.type)
Jce.LIST -> { // list
JceDecoder.structureHierarchy++
var count: Int = 0
nextHead() // avoid shadowing, don't remove
repeat(skipToHeadAndUseIfPossibleOrFail(0, message = { "tag 0 not found when skipping list" }) { head ->
readJceIntValue(head).also { count = it }
}) {
skipField(currentHead.type)
if (it != count - 1) { // don't read last head
nextHead()
}
}
JceDecoder.structureHierarchy--
}
}
Jce.STRUCT_BEGIN -> {
JceDecoder.println {"skip struct!"}
fun skipToStructEnd() {
Jce.STRUCT_BEGIN -> {
JceDecoder.structureHierarchy++
var head: JceHead
do {
head = nextHead()
skipField(head.type)
} while (head.type != Jce.STRUCT_END)
JceDecoder.structureHierarchy--
}
skipToStructEnd()
}
Jce.STRUCT_END, Jce.ZERO_TYPE -> {
Unit
}
Jce.SIMPLE_LIST -> {
JceDecoder.println { "skip simple list!" }
var head = nextHead()
check(head.type == Jce.BYTE) { "bad simple list element type: " + head.type }
check(head.tag == 0) { "simple list element tag must be 0, but was ${head.tag}" }

head = nextHead()
check(head.tag == 0) { "tag for size for simple list must be 0, but was ${head.tag}" }
this.input.discardExact(readJceIntValue(head))
Jce.STRUCT_END, Jce.ZERO_TYPE -> {
}
Jce.SIMPLE_LIST -> {
JceDecoder.structureHierarchy++
var head = nextHead()
check(head.type == Jce.BYTE) { "bad simple list element type: " + head.type }
check(head.tag == 0) { "simple list element tag must be 0, but was ${head.tag}" }

head = nextHead()
check(head.tag == 0) { "tag for size for simple list must be 0, but was ${head.tag}" }
this.input.discardExact(readJceIntValue(head))
JceDecoder.structureHierarchy--
}
else -> error("invalid type: $type")
}
else -> error("invalid type: $type")
}

// region readers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import kotlinx.io.core.writeFully
import kotlinx.serialization.MissingFieldException
import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceInput
import net.mamoe.mirai.qqandroid.io.serialization.jce.writeJceHead
import net.mamoe.mirai.qqandroid.io.serialization.jce.*
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
Expand Down Expand Up @@ -42,6 +39,9 @@ internal const val ZERO_TYPE: Byte = 12
*/
@Suppress("INVISIBLE_MEMBER") // bug
internal class JceInputTest {
init {
JceDecoder.debuggingMode = true
}

@Test
fun testIntToStructMap() {
Expand Down Expand Up @@ -109,31 +109,33 @@ internal class JceInputTest {
val input = buildPacket {
writeJceHead(MAP, 0) // TestSerializableClassB
writeJceHead(BYTE, 0)
writeByte(1)
writeByte(1);

writeJceHead(STRUCT_BEGIN, 0);
{
writeJceHead(INT, 0)
writeInt(123)
writeJceHead(STRUCT_BEGIN, 0);
{
writeJceHead(INT, 0)
writeInt(123)

writeJceHead(STRUCT_BEGIN, 123); // TestSerializableClassC
writeJceHead(STRUCT_BEGIN, 123); // TestSerializableClassC
{
writeJceHead(INT, 5)
writeInt(123123)
}()
writeJceHead(STRUCT_END, 0)

writeJceHead(INT, 5)
writeInt(9)
}()
writeJceHead(STRUCT_END, 0)

writeJceHead(STRUCT_BEGIN, 1);
{
writeJceHead(INT, 5)
writeInt(123123)
}()
writeJceHead(STRUCT_END, 0)

writeJceHead(INT, 5)
writeInt(9)
}()
writeJceHead(STRUCT_END, 0)

writeJceHead(STRUCT_BEGIN, 1);
{
writeJceHead(INT, 5)
writeInt(123123)
}()
writeJceHead(STRUCT_END, 0)

writeJceHead(STRING1, 1)
writeByte(1)
Expand Down

0 comments on commit 948658c

Please sign in to comment.