Commit 2acca0c2 authored by Him188's avatar Him188

Jce complex nesting support

parent e375d17f
...@@ -111,6 +111,42 @@ internal class JceDecoder( ...@@ -111,6 +111,42 @@ internal class JceDecoder(
} }
} }
private val MapReader: MapReaderImpl = MapReaderImpl()
private inner class MapReaderImpl : AbstractDecoder() {
override fun decodeSequentially(): Boolean = true
override fun decodeElementIndex(descriptor: SerialDescriptor): Int = error("should not be reached")
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))
state = !state
return this@JceDecoder.beginStructure(descriptor, *typeParams)
}
override fun decodeByte(): Byte = jce.useHead { jce.readJceByteValue(it) }
override fun decodeShort(): Short = jce.useHead { jce.readJceShortValue(it) }
override fun decodeInt(): Int = jce.useHead { jce.readJceIntValue(it) }
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}")
// 不读下一个 head
return jce.useHead { jce.readJceIntValue(it) }.also { println("listSize=$it") }
}
}
override fun endStructure(descriptor: SerialDescriptor) { override fun endStructure(descriptor: SerialDescriptor) {
println("endStructure: $descriptor") println("endStructure: $descriptor")
if (currentTagOrNull?.isSimpleByteArray == true) { if (currentTagOrNull?.isSimpleByteArray == true) {
...@@ -123,9 +159,11 @@ internal class JceDecoder( ...@@ -123,9 +159,11 @@ internal class JceDecoder(
while (true) { while (true) {
val currentHead = jce.currentHeadOrNull ?: return val currentHead = jce.currentHeadOrNull ?: return
if (currentHead.type == Jce.STRUCT_END) { if (currentHead.type == Jce.STRUCT_END) {
jce.prepareNextHead()
println("current end")
break break
} }
println("skipping") println("current $currentHead")
jce.skipField(currentHead.type) jce.skipField(currentHead.type)
jce.prepareNextHead() jce.prepareNextHead()
} }
...@@ -145,7 +183,7 @@ internal class JceDecoder( ...@@ -145,7 +183,7 @@ internal class JceDecoder(
println("!! MAP") println("!! MAP")
return jce.skipToHeadAndUseIfPossibleOrFail(popTag().id) { return jce.skipToHeadAndUseIfPossibleOrFail(popTag().id) {
it.checkType(Jce.MAP) it.checkType(Jce.MAP)
ListReader MapReader
} }
} }
StructureKind.LIST -> { StructureKind.LIST -> {
...@@ -171,9 +209,15 @@ internal class JceDecoder( ...@@ -171,9 +209,15 @@ internal class JceDecoder(
println("!! CLASS") println("!! CLASS")
println("decoderTag: $currentTag") println("decoderTag: $currentTag")
println("jceHead: " + jce.currentHeadOrNull) println("jceHead: " + jce.currentHeadOrNull)
return jce.skipToHeadAndUseIfPossibleOrFail(popTag().id) { return jce.skipToHeadAndUseIfPossibleOrFail(popTag().id) { jceHead ->
it.checkType(Jce.STRUCT_BEGIN) jceHead.checkType(Jce.STRUCT_BEGIN)
this@JceDecoder
// TODO: 2020/3/8 检查是否需要 scope 化
repeat(descriptor.elementsCount) {
pushTag(descriptor.getTag(descriptor.elementsCount - it - 1)) // better performance
}
this // independent tag stack
} }
} }
......
...@@ -42,7 +42,7 @@ internal const val ZERO_TYPE: Byte = 12 ...@@ -42,7 +42,7 @@ internal const val ZERO_TYPE: Byte = 12
internal class JceInputTest { internal class JceInputTest {
@Test @Test
fun testNestedJceStruct() { fun testFuckingComprehensiveStruct() {
@Serializable @Serializable
data class TestSerializableClassC( data class TestSerializableClassC(
@JceId(5) val value3: Int = 123123 @JceId(5) val value3: Int = 123123
...@@ -51,15 +51,77 @@ internal class JceInputTest { ...@@ -51,15 +51,77 @@ internal class JceInputTest {
@Serializable @Serializable
data class TestSerializableClassB( data class TestSerializableClassB(
@JceId(0) val value: Int, @JceId(0) val value: Int,
@JceId(123) val nested2: TestSerializableClassC @JceId(123) val nested2: TestSerializableClassC,
@JceId(5) val value5: Int
)
@Serializable
data class TestSerializableClassA(
@JceId(0) val map: Map<TestSerializableClassB, TestSerializableClassC>
)
val input = buildPacket {
writeJceHead(MAP, 0) // TestSerializableClassB
writeJceHead(BYTE, 0)
writeByte(1)
writeJceHead(STRUCT_BEGIN, 0);
{
writeJceHead(INT, 0)
writeInt(123)
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)
}
assertEquals(
TestSerializableClassA(
mapOf(
TestSerializableClassB(123, TestSerializableClassC(123123), 9)
to TestSerializableClassC(123123)
)
),
JceNew.UTF_8.load(TestSerializableClassA.serializer(), input)
)
}
@Test
fun testNestedJceStruct() {
@Serializable
data class TestSerializableClassC(
@JceId(5) val value3: Int
)
@Serializable
data class TestSerializableClassB(
@JceId(0) val value: Int,
@JceId(123) val nested2: TestSerializableClassC,
@JceId(5) val value5: Int
) )
@Serializable @Serializable
data class TestSerializableClassA( data class TestSerializableClassA(
@JceId(0) val value1: Int, @JceId(0) val value1: Int,
@JceId(4) val notOptional: Int,
@JceId(1) val nestedStruct: TestSerializableClassB, @JceId(1) val nestedStruct: TestSerializableClassB,
@JceId(2) val optional: Int = 3, @JceId(2) val optional: Int = 3
@JceId(4) val notOptional: Int
) )
val input = buildPacket { val input = buildPacket {
...@@ -78,8 +140,8 @@ internal class JceInputTest { ...@@ -78,8 +140,8 @@ internal class JceInputTest {
}() }()
writeJceHead(STRUCT_END, 0) writeJceHead(STRUCT_END, 0)
writeJceHead(INT, 2) // 多余 writeJceHead(INT, 5)
writeInt(123) writeInt(9)
}() }()
writeJceHead(STRUCT_END, 0) writeJceHead(STRUCT_END, 0)
...@@ -88,7 +150,11 @@ internal class JceInputTest { ...@@ -88,7 +150,11 @@ internal class JceInputTest {
} }
assertEquals( assertEquals(
TestSerializableClassA(444, TestSerializableClassB(123, TestSerializableClassC(123123)), notOptional = 5), TestSerializableClassA(
444,
5,
TestSerializableClassB(123, TestSerializableClassC(123123), 9)
),
JceNew.UTF_8.load(TestSerializableClassA.serializer(), input) JceNew.UTF_8.load(TestSerializableClassA.serializer(), input)
) )
} }
......
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