Commit 2260d331 authored by Him188's avatar Him188

Support ByteArray

parent 91df7298
......@@ -35,6 +35,7 @@ internal class JceDecoder(
this.getElementDescriptor(index).isNullable
)
}
fun SerialDescriptor.getJceTagId(index: Int): Int {
return getElementAnnotations(index).filterIsInstance<JceId>().single().id
}
......@@ -43,26 +44,32 @@ internal class JceDecoder(
private val ByteArraySerializer = ByteArraySerializer()
// TODO: 2020/3/6 can be object
private inner class SimpleByteArrayReader() : CompositeDecoder by this {
private inner class SimpleByteArrayReader : CompositeDecoder by this {
override fun decodeSequentially(): Boolean = true
override fun decodeByteElement(descriptor: SerialDescriptor, index: Int): Byte {
return jce.input.readByte()
println("decodeByteElement: $index")
return jce.input.readByte().also { println("read: $it") }
}
override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
return 0
error("should not be reached")
}
override fun decodeCollectionSize(descriptor: SerialDescriptor): Int {
return jce.useHead { jce.readJceIntValue(it) }
// 不要读下一个 head
return jce.currentHead.let { jce.readJceIntValue(it) }.also { println("simpleListSize=$it") }
}
}
// TODO: 2020/3/6 can be object
private inner class ListReader() : CompositeDecoder by this {
override fun decodeSequentially(): Boolean = false
private inner class ListReader : CompositeDecoder by this {
override fun decodeSequentially(): Boolean = true
override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
return 0
error("should not be reached")
}
override fun endStructure(descriptor: SerialDescriptor) {
println("endStructure: ${descriptor.serialName}")
}
override fun decodeCollectionSize(descriptor: SerialDescriptor): Int {
......@@ -70,12 +77,24 @@ internal class JceDecoder(
}
}
override fun endStructure(descriptor: SerialDescriptor) {
if (descriptor == ByteArraySerializer.descriptor) {
jce.prepareNextHead() // list 里面没读 head
}
super.endStructure(descriptor)
}
override fun beginStructure(descriptor: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeDecoder {
println("beginStructure: ${descriptor.serialName}")
if (descriptor == ByteArraySerializer.descriptor) {
println("!! ByteArray")
println("decoderTag: $currentTagOrNull")
println("jceHead: " + jce.currentHeadOrNull)
return jce.skipToHeadAndUseIfPossibleOrFail(popTag().id) {
println("listHead: $it")
when (it.type) {
Jce.SIMPLE_LIST -> SimpleByteArrayReader()
Jce.LIST -> ListReader()
Jce.SIMPLE_LIST -> SimpleByteArrayReader().also { jce.prepareNextHead() } // 无用的元素类型
Jce.LIST -> error(""); //ListReader()
else -> error("type mismatch. Expected SIMPLE_LIST or LIST, got ${it.type} instead")
}
}
......@@ -86,22 +105,22 @@ internal class JceDecoder(
}
StructureKind.LIST -> ListReader()
else -> this
else -> this@JceDecoder
}
}
override fun <T> decodeSerializableValue(deserializer: DeserializationStrategy<T>): T {
println("decodeSerializableValue: ${deserializer.descriptor}")
println(
"decodeSerializableValue: ${deserializer.descriptor.toString().substringBefore('(')
.substringAfterLast('.')}"
)
return super.decodeSerializableValue(deserializer)
}
private var currentIndex = 0
override fun decodeSequentially(): Boolean = false
override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
val jceHead = jce.currentHeadOrNull ?: return CompositeDecoder.READ_DONE
repeat(descriptor.elementsCount){
repeat(descriptor.elementsCount) {
val tag = descriptor.getJceTagId(it)
if (tag == jceHead.tag) {
return it
......@@ -116,10 +135,6 @@ internal class JceDecoder(
return super.decodeTaggedNull(tag)
}
override fun <T : Any> decodeNullableSerializableValue(deserializer: DeserializationStrategy<T?>): T? {
return super.decodeNullableSerializableValue(deserializer)
}
override fun decodeTaggedValue(tag: JceTag): Any {
println("decodeTaggedValue")
return super.decodeTaggedValue(tag)
......@@ -149,14 +164,6 @@ internal class JceDecoder(
override fun decodeTaggedString(tag: JceTag): String =
jce.skipToHeadAndUseIfPossibleOrFail(tag.id) { jce.readJceStringValue(it) }
override fun decodeTaggedEnum(tag: JceTag, enumDescription: SerialDescriptor): Int {
return super.decodeTaggedEnum(tag, enumDescription)
}
override fun decodeTaggedChar(tag: JceTag): Char {
return super.decodeTaggedChar(tag)
}
override fun decodeTaggedNotNullMark(tag: JceTag): Boolean {
return jce.skipToHeadOrNull(tag.id) != null
}
......
......@@ -3,6 +3,7 @@
package net.mamoe.mirai.qqandroid.io.serialization
import io.ktor.utils.io.core.*
import kotlinx.serialization.MissingFieldException
import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceInput
......@@ -38,20 +39,73 @@ internal const val ZERO_TYPE: Byte = 12
*/
@Suppress("INVISIBLE_MEMBER") // bug
internal class JceInputTest {
@Serializable
data class TestSerializableClassA(
@JceId(0) val byte: Byte = 66,
@JceId(1) val short: Short = 123,
@JceId(3) val int: Int = 123456,
@JceId(8) val float: Float = 123f,
@JceId(15) val long: Long = 123456789123456789L,
@JceId(16) val double: Double = 123456.0,
@JceId(17) val boolean: Boolean = true,
@JceId(11111) val nullable: Int? = null
)
@Test
fun testSimpleByteArray() {
@Serializable
data class TestSerializableClassA(
@JceId(0) val byteArray: ByteArray = byteArrayOf(1, 2, 3),
@JceId(3) val byteArray2: ByteArray = byteArrayOf(1, 2, 3, 4)
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
other as TestSerializableClassA
if (!byteArray.contentEquals(other.byteArray)) return false
if (!byteArray2.contentEquals(other.byteArray2)) return false
return true
}
override fun hashCode(): Int {
var result = byteArray.contentHashCode()
result = 31 * result + byteArray2.contentHashCode()
return result
}
}
val input = buildPacket {
writeJceHead(SIMPLE_LIST, 0)
writeJceHead(BYTE, 0)
writeJceHead(BYTE, 0)
byteArrayOf(1, 2, 3).let {
writeByte(it.size.toByte())
writeFully(it)
}
writeJceHead(SIMPLE_LIST, 3)
writeJceHead(BYTE, 0)
writeJceHead(BYTE, 0)
byteArrayOf(1, 2, 3, 4).let {
writeByte(it.size.toByte())
writeFully(it)
}
}
assertEquals(TestSerializableClassA(), JceNew.UTF_8.load(TestSerializableClassA.serializer(), input))
}
@Test
fun testSerializableClassA() {
@Serializable
data class TestSerializableClassA(
@JceId(0) val byte: Byte = 66,
@JceId(1) val short: Short = 123,
@JceId(3) val int: Int = 123456,
@JceId(8) val float: Float = 123f,
@JceId(15) val long: Long = 123456789123456789L,
@JceId(16) val double: Double = 123456.0,
@JceId(17) val boolean: Boolean = true,
@JceId(11111) val nullable: Int? = null,
@JceId(111112) val nullable2: Int? = null,
@JceId(111113) val optional: Int = 123
)
val input = buildPacket {
writeJceHead(BYTE, 0)
writeByte(66)
......@@ -72,6 +126,25 @@ internal class JceInputTest {
assertEquals(TestSerializableClassA(), JceNew.UTF_8.load(TestSerializableClassA.serializer(), input))
}
@Test
fun testNoSuchField() {
@Serializable
data class TestSerializableClassA(
@JceId(0) val byte: Byte = 66,
@JceId(1) val short: Short = 123,
@JceId(3) val int: Int
)
val input = buildPacket {
writeJceHead(BYTE, 0)
writeByte(66)
writeJceHead(SHORT, 1)
writeShort(123)
}
assertFailsWith<MissingFieldException> { JceNew.UTF_8.load(TestSerializableClassA.serializer(), input) }
}
@Test
fun testHeadSkip() {
val input = JceInput(buildPacket {
......
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