Commit ce7af37e authored by Him188's avatar Him188

Migrate to new Jce serializer

parent 2acca0c2
......@@ -8,7 +8,7 @@ import kotlinx.serialization.SerializationStrategy
interface IOFormat : SerialFormat {
fun <T> dump(serializer: SerializationStrategy<T>, output: Output): ByteArray
fun <T> dumpTo(serializer: SerializationStrategy<T>, ojb: T, output: Output)
fun <T> load(deserializer: DeserializationStrategy<T>, input: Input): T
}
......@@ -21,7 +21,24 @@ import kotlinx.serialization.modules.SerialModule
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.ProtoBuf
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.BYTE
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.DOUBLE
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.FLOAT
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.INT
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.JCE_MAX_STRING_LENGTH
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.LIST
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.LONG
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.MAP
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.SHORT
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.SIMPLE_LIST
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.STRING1
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.STRING4
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.STRUCT_BEGIN
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.STRUCT_END
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce.Companion.ZERO_TYPE
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceHead
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
import net.mamoe.mirai.utils.io.readString
import net.mamoe.mirai.utils.io.toReadPacket
......@@ -36,14 +53,14 @@ enum class JceCharset(val kotlinCharset: Charset) {
UTF8(Charset.forName("UTF8"))
}
internal fun getSerialId(desc: SerialDescriptor, index: Int): Int? = desc.findAnnotation<ProtoId>(index)?.id
internal fun getSerialId(desc: SerialDescriptor, index: Int): Int? = desc.findAnnotation<JceId>(index)?.id
/**
* Jce 数据结构序列化和反序列化工具, 能将 kotlinx.serialization 通用的注解标记格式的 `class` 序列化为 [ByteArray]
*/
@Suppress("DEPRECATION_ERROR")
@OptIn(InternalSerializationApi::class)
class Jce private constructor(private val charset: JceCharset, override val context: SerialModule = EmptyModule) :
class JceOld private constructor(private val charset: JceCharset, override val context: SerialModule = EmptyModule) :
SerialFormat, BinaryFormat {
private inner class ListWriter(
......@@ -101,7 +118,7 @@ class Jce private constructor(private val charset: JceCharset, override val cont
private open inner class JceEncoder(
internal val output: BytePacketBuilder
) : TaggedEncoder<Int>() {
override val context get() = this@Jce.context
override val context get() = this@JceOld.context
override fun SerialDescriptor.getTag(index: Int): Int {
return getSerialId(this, index) ?: error("cannot find @SerialId")
......@@ -753,10 +770,10 @@ class Jce private constructor(private val charset: JceCharset, override val cont
@Suppress("MemberVisibilityCanBePrivate")
companion object {
val UTF8 = Jce(JceCharset.UTF8)
val GBK = Jce(JceCharset.GBK)
val UTF8 = JceOld(JceCharset.UTF8)
val GBK = JceOld(JceCharset.GBK)
fun byCharSet(c: JceCharset): Jce {
fun byCharSet(c: JceCharset): JceOld {
return if (c == JceCharset.UTF8) {
UTF8
} else {
......@@ -764,22 +781,6 @@ class Jce private constructor(private val charset: JceCharset, override val cont
}
}
internal const val BYTE: Byte = 0
internal const val DOUBLE: Byte = 5
internal const val FLOAT: Byte = 4
internal const val INT: Byte = 2
internal const val JCE_MAX_STRING_LENGTH = 104857600
internal const val LIST: Byte = 9
internal const val LONG: Byte = 3
internal const val MAP: Byte = 8
internal const val SHORT: Byte = 1
internal const val SIMPLE_LIST: Byte = 13
internal const val STRING1: Byte = 6
internal const val STRING4: Byte = 7
internal const val STRUCT_BEGIN: Byte = 10
internal const val STRUCT_END: Byte = 11
internal const val ZERO_TYPE: Byte = 12
private fun Any?.getClassName(): String =
(if (this == null) Unit::class else this::class).qualifiedName?.split(".")?.takeLast(2)?.joinToString(".")
?: "<unnamed class>"
......@@ -815,7 +816,7 @@ class Jce private constructor(private val charset: JceCharset, override val cont
}
}
internal inline fun <R> Jce.JceInput.skipToTagOrNull(tag: Int, block: (JceHead) -> R): R? {
internal inline fun <R> JceOld.JceInput.skipToTagOrNull(tag: Int, block: (JceHead) -> R): R? {
// println("skipping to $tag start")
while (true) {
if (isEndOfInput) { // 读不了了
......
......@@ -10,7 +10,6 @@
package net.mamoe.mirai.qqandroid.io.serialization.jce
import kotlinx.io.core.*
import net.mamoe.mirai.qqandroid.io.serialization.Jce
import net.mamoe.mirai.qqandroid.io.serialization.JceCharset
import net.mamoe.mirai.utils.io.readString
......
......@@ -9,8 +9,8 @@
package net.mamoe.mirai.qqandroid.io.serialization.jce
import kotlinx.io.core.Input
import kotlinx.io.core.Output
import kotlinx.io.core.*
import kotlinx.serialization.BinaryFormat
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialFormat
import kotlinx.serialization.SerializationStrategy
......@@ -18,26 +18,56 @@ import kotlinx.serialization.modules.EmptyModule
import kotlinx.serialization.modules.SerialModule
import net.mamoe.mirai.qqandroid.io.serialization.IOFormat
import net.mamoe.mirai.qqandroid.io.serialization.JceCharset
import net.mamoe.mirai.qqandroid.io.serialization.JceOld
import net.mamoe.mirai.utils.io.toReadPacket
/**
* Jce 数据结构序列化和反序列化器.
*
* @author Him188
*/
class JceNew(
class Jce(
override val context: SerialModule,
val charset: JceCharset
) : SerialFormat, IOFormat {
override fun <T> dump(serializer: SerializationStrategy<T>, output: Output): ByteArray {
TODO("Not yet implemented")
) : SerialFormat, IOFormat, BinaryFormat {
override fun <T> dumpTo(serializer: SerializationStrategy<T>, ojb: T, output: Output) {
output.writePacket(JceOld.byCharSet(this.charset).dumpAsPacket(serializer, ojb))
}
override fun <T> load(deserializer: DeserializationStrategy<T>, input: Input): T {
return JceDecoder(JceInput(input, charset), context).decodeSerializableValue(deserializer)
}
override fun <T> dump(serializer: SerializationStrategy<T>, value: T): ByteArray {
return buildPacket { dumpTo(serializer, value, this) }.readBytes()
}
override fun <T> load(deserializer: DeserializationStrategy<T>, bytes: ByteArray): T {
return load(deserializer, bytes.toReadPacket())
}
companion object {
val UTF_8 = JceNew(EmptyModule, JceCharset.UTF8)
val GBK = JceNew(EmptyModule, JceCharset.GBK)
val UTF_8 = Jce(EmptyModule, JceCharset.UTF8)
val GBK = Jce(EmptyModule, JceCharset.GBK)
fun byCharSet(c: JceCharset): Jce {
return if (c == JceCharset.UTF8) UTF_8 else GBK
}
internal const val BYTE: Byte = 0
internal const val DOUBLE: Byte = 5
internal const val FLOAT: Byte = 4
internal const val INT: Byte = 2
internal const val JCE_MAX_STRING_LENGTH = 104857600
internal const val LIST: Byte = 9
internal const val LONG: Byte = 3
internal const val MAP: Byte = 8
internal const val SHORT: Byte = 1
internal const val SIMPLE_LIST: Byte = 13
internal const val STRING1: Byte = 6
internal const val STRING4: Byte = 7
internal const val STRUCT_BEGIN: Byte = 10
internal const val STRUCT_END: Byte = 11
internal const val ZERO_TYPE: Byte = 12
}
}
\ No newline at end of file
......@@ -11,7 +11,6 @@ package net.mamoe.mirai.qqandroid.io.serialization.jce
import kotlinx.io.core.Output
import kotlinx.serialization.SerialInfo
import net.mamoe.mirai.qqandroid.io.serialization.Jce
/**
......@@ -27,15 +26,47 @@ annotation class JceId(val id: Int)
* 保留这个结构, 为将来增加功能的兼容性.
*/
@PublishedApi
internal data class JceTag(
val id: Int,
val isNullable: Boolean
){
internal abstract class JceTag {
abstract val id: Int
abstract val isNullable: Boolean
internal var isSimpleByteArray: Boolean = false
}
internal sealed class JceTagListElement(
override val isNullable: Boolean
) : JceTag(){
override val id: Int get() = 0
object Nullable : JceTagListElement(true)
object NotNull : JceTagListElement(false)
}
internal sealed class JceTagMapEntryKey(
override val isNullable: Boolean
) : JceTag(){
override val id: Int get() = 0
object Nullable : JceTagMapEntryKey(true)
object NotNull : JceTagMapEntryKey(false)
}
internal sealed class JceTagMapEntryValue(
override val isNullable: Boolean
) : JceTag() {
override val id: Int get() = 1
object Nullable : JceTagMapEntryValue(true)
object NotNull : JceTagMapEntryValue(false)
}
internal data class JceTagCommon(
override val id: Int,
override val isNullable: Boolean
) : JceTag()
fun JceHead.checkType(type: Byte) {
check(this.type == type) {"type mismatch. Expected $type, actual ${this.type}"}
check(this.type == type) { "type mismatch. Expected $type, actual ${this.type}" }
}
@PublishedApi
......
......@@ -18,21 +18,29 @@ import kotlinx.serialization.SerialDescriptor
import kotlinx.serialization.SerializationStrategy
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.ProtoBuf
import net.mamoe.mirai.qqandroid.io.serialization.jce.Jce
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestDataVersion2
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestDataVersion3
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPacket
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.firstValue
import net.mamoe.mirai.utils.io.read
import net.mamoe.mirai.utils.io.readPacketExact
import net.mamoe.mirai.utils.io.toReadPacket
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
fun <T : JceStruct> ByteArray.loadAs(deserializer: DeserializationStrategy<T>, c: JceCharset = JceCharset.UTF8): T {
return Jce.byCharSet(c).load(deserializer, this)
return Jce.byCharSet(c).load(deserializer, this.toReadPacket())
}
fun <T : JceStruct> BytePacketBuilder.writeJceStruct(serializer: SerializationStrategy<T>, struct: T, charset: JceCharset = JceCharset.GBK) {
this.writePacket(Jce.byCharSet(charset).dumpAsPacket(serializer, struct))
fun <T : JceStruct> BytePacketBuilder.writeJceStruct(
serializer: SerializationStrategy<T>,
struct: T,
charset: JceCharset = JceCharset.GBK
) {
Jce.byCharSet(charset).dumpTo(serializer, struct, this)
}
fun <T : JceStruct> ByteReadPacket.readJceStruct(
......@@ -40,7 +48,8 @@ fun <T : JceStruct> ByteReadPacket.readJceStruct(
charset: JceCharset = JceCharset.UTF8,
length: Int = this.remaining.toInt()
): T {
return Jce.byCharSet(charset).load(serializer, this, length)
@OptIn(MiraiInternalAPI::class)
return Jce.byCharSet(charset).load(serializer, this.readPacketExact(length))
}
/**
......@@ -82,7 +91,8 @@ fun <R> ByteReadPacket.decodeUniRequestPacketAndDeserialize(name: String? = null
})
}
fun <T : JceStruct> T.toByteArray(serializer: SerializationStrategy<T>, c: JceCharset = JceCharset.GBK): ByteArray = Jce.byCharSet(c).dump(serializer, this)
fun <T : JceStruct> T.toByteArray(serializer: SerializationStrategy<T>, c: JceCharset = JceCharset.GBK): ByteArray =
Jce.byCharSet(c).dump(serializer, this)
fun <T : ProtoBuf> BytePacketBuilder.writeProtoBuf(serializer: SerializationStrategy<T>, v: T) {
this.writeFully(v.toByteArray(serializer))
......
......@@ -10,138 +10,138 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.jce
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
@Serializable
internal class BigDataChannel(
@ProtoId(0) val vBigdataIplists: List<BigDataIpList>,
@ProtoId(1) val sBigdataSigSession: ByteArray? = null,
@ProtoId(2) val sBigdataKeySession: ByteArray? = null,
@ProtoId(3) val uSigUin: Long? = null,
@ProtoId(4) val iConnectFlag: Int? = 1,
@ProtoId(5) val vBigdataPbBuf: ByteArray? = null
@JceId(0) val vBigdataIplists: List<BigDataIpList>,
@JceId(1) val sBigdataSigSession: ByteArray? = null,
@JceId(2) val sBigdataKeySession: ByteArray? = null,
@JceId(3) val uSigUin: Long? = null,
@JceId(4) val iConnectFlag: Int? = 1,
@JceId(5) val vBigdataPbBuf: ByteArray? = null
) : JceStruct
@Serializable
internal class BigDataIpInfo(
@ProtoId(0) val uType: Long,
@ProtoId(1) val sIp: String = "",
@ProtoId(2) val uPort: Long
@JceId(0) val uType: Long,
@JceId(1) val sIp: String = "",
@JceId(2) val uPort: Long
) : JceStruct
@Serializable
internal class BigDataIpList(
@ProtoId(0) val uServiceType: Long,
@ProtoId(1) val vIplist: List<BigDataIpInfo>,
@ProtoId(2) val netSegConfs: List<NetSegConf>? = null,
@ProtoId(3) val ufragmentSize: Long? = null
@JceId(0) val uServiceType: Long,
@JceId(1) val vIplist: List<BigDataIpInfo>,
@JceId(2) val netSegConfs: List<NetSegConf>? = null,
@JceId(3) val ufragmentSize: Long? = null
) : JceStruct
@Serializable
internal class ClientLogConfig(
@ProtoId(1) val type: Int,
@ProtoId(2) val timeStart: TimeStamp? = null,
@ProtoId(3) val timeFinish: TimeStamp? = null,
@ProtoId(4) val loglevel: Byte? = null,
@ProtoId(5) val cookie: Int? = null,
@ProtoId(6) val lseq: Long? = null
@JceId(1) val type: Int,
@JceId(2) val timeStart: TimeStamp? = null,
@JceId(3) val timeFinish: TimeStamp? = null,
@JceId(4) val loglevel: Byte? = null,
@JceId(5) val cookie: Int? = null,
@JceId(6) val lseq: Long? = null
) : JceStruct
@Serializable
internal class DomainIpChannel(
@ProtoId(0) val vDomainIplists: List<DomainIpList>
@JceId(0) val vDomainIplists: List<DomainIpList>
) : JceStruct
@Serializable
internal class DomainIpInfo(
@ProtoId(1) val uIp: Int,
@ProtoId(2) val uPort: Int
@JceId(1) val uIp: Int,
@JceId(2) val uPort: Int
) : JceStruct
@Serializable
internal class DomainIpList(
@ProtoId(0) val uDomainType: Int,
@ProtoId(1) val vIplist: List<DomainIpInfo>
@JceId(0) val uDomainType: Int,
@JceId(1) val vIplist: List<DomainIpInfo>
) : JceStruct
@Serializable
internal class FileStoragePushFSSvcList(
@ProtoId(0) val vUpLoadList: List<FileStorageServerListInfo>,
@ProtoId(1) val vPicDownLoadList: List<FileStorageServerListInfo>,
@ProtoId(2) val vGPicDownLoadList: List<FileStorageServerListInfo>? = null,
@ProtoId(3) val vQzoneProxyServiceList: List<FileStorageServerListInfo>? = null,
@ProtoId(4) val vUrlEncodeServiceList: List<FileStorageServerListInfo>? = null,
@ProtoId(5) val bigDataChannel: BigDataChannel? = null,
@ProtoId(6) val vVipEmotionList: List<FileStorageServerListInfo>? = null,
@ProtoId(7) val vC2CPicDownList: List<FileStorageServerListInfo>? = null,
@ProtoId(8) val fmtIPInfo: FmtIPInfo? = null,
@ProtoId(9) val domainIpChannel: DomainIpChannel? = null,
@ProtoId(10) val pttlist: ByteArray? = null
@JceId(0) val vUpLoadList: List<FileStorageServerListInfo>,
@JceId(1) val vPicDownLoadList: List<FileStorageServerListInfo>,
@JceId(2) val vGPicDownLoadList: List<FileStorageServerListInfo>? = null,
@JceId(3) val vQzoneProxyServiceList: List<FileStorageServerListInfo>? = null,
@JceId(4) val vUrlEncodeServiceList: List<FileStorageServerListInfo>? = null,
@JceId(5) val bigDataChannel: BigDataChannel? = null,
@JceId(6) val vVipEmotionList: List<FileStorageServerListInfo>? = null,
@JceId(7) val vC2CPicDownList: List<FileStorageServerListInfo>? = null,
@JceId(8) val fmtIPInfo: FmtIPInfo? = null,
@JceId(9) val domainIpChannel: DomainIpChannel? = null,
@JceId(10) val pttlist: ByteArray? = null
) : JceStruct
@Serializable
internal class FileStorageServerListInfo(
@ProtoId(1) val sIP: String = "",
@ProtoId(2) val iPort: Int
@JceId(1) val sIP: String = "",
@JceId(2) val iPort: Int
) : JceStruct
@Serializable
internal class FmtIPInfo(
@ProtoId(0) val sGateIp: String = "",
@ProtoId(1) val iGateIpOper: Long
@JceId(0) val sGateIp: String = "",
@JceId(1) val iGateIpOper: Long
) : JceStruct
@Serializable
internal class NetSegConf(
@ProtoId(0) val uint32NetType: Long? = null,
@ProtoId(1) val uint32Segsize: Long? = null,
@ProtoId(2) val uint32Segnum: Long? = null,
@ProtoId(3) val uint32Curconnnum: Long? = null
@JceId(0) val uint32NetType: Long? = null,
@JceId(1) val uint32Segsize: Long? = null,
@JceId(2) val uint32Segnum: Long? = null,
@JceId(3) val uint32Curconnnum: Long? = null
) : JceStruct
@Suppress("ArrayInDataClass")
@Serializable
internal data class PushReq(
@ProtoId(1) val type: Int,
@ProtoId(2) val jcebuf: ByteArray,
@ProtoId(3) val seq: Long
@JceId(1) val type: Int,
@JceId(2) val jcebuf: ByteArray,
@JceId(3) val seq: Long
) : JceStruct, Packet
@Serializable
internal class PushResp(
@ProtoId(1) val type: Int,
@ProtoId(2) val seq: Long,
@ProtoId(3) val jcebuf: ByteArray? = null
@JceId(1) val type: Int,
@JceId(2) val seq: Long,
@JceId(3) val jcebuf: ByteArray? = null
) : JceStruct
@Serializable
internal class SsoServerList(
@ProtoId(1) val v2G3GList: List<SsoServerListInfo>,
@ProtoId(3) val vWifiList: List<SsoServerListInfo>,
@ProtoId(4) val iReconnect: Int,
@ProtoId(5) val testSpeed: Byte? = null,
@ProtoId(6) val useNewList: Byte? = null,
@ProtoId(7) val iMultiConn: Int? = 1,
@ProtoId(8) val vHttp2g3glist: List<SsoServerListInfo>? = null,
@ProtoId(9) val vHttpWifilist: List<SsoServerListInfo>? = null
@JceId(1) val v2G3GList: List<SsoServerListInfo>,
@JceId(3) val vWifiList: List<SsoServerListInfo>,
@JceId(4) val iReconnect: Int,
@JceId(5) val testSpeed: Byte? = null,
@JceId(6) val useNewList: Byte? = null,
@JceId(7) val iMultiConn: Int? = 1,
@JceId(8) val vHttp2g3glist: List<SsoServerListInfo>? = null,
@JceId(9) val vHttpWifilist: List<SsoServerListInfo>? = null
) : JceStruct
@Serializable
internal class SsoServerListInfo(
@ProtoId(1) val sIP: String = "",
@ProtoId(2) val iPort: Int,
@ProtoId(3) val linkType: Byte,
@ProtoId(4) val proxy: Byte,
@ProtoId(5) val protocolType: Byte? = null,
@ProtoId(6) val iTimeOut: Int? = 10
@JceId(1) val sIP: String = "",
@JceId(2) val iPort: Int,
@JceId(3) val linkType: Byte,
@JceId(4) val proxy: Byte,
@JceId(5) val protocolType: Byte? = null,
@JceId(6) val iTimeOut: Int? = 10
) : JceStruct
@Serializable
internal class TimeStamp(
@ProtoId(1) val year: Int,
@ProtoId(2) val month: Byte,
@ProtoId(3) val day: Byte,
@ProtoId(4) val hour: Byte
@JceId(1) val year: Int,
@JceId(2) val month: Byte,
@JceId(3) val day: Byte,
@JceId(4) val hour: Byte
) : JceStruct
......@@ -10,71 +10,71 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.jce
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
@Suppress("ArrayInDataClass")
@Serializable
internal data class RequestPushNotify(
@ProtoId(0) val uin: Long? = 0L,
@ProtoId(1) val ctype: Byte = 0,
@ProtoId(2) val strService: String?,
@ProtoId(3) val strCmd: String?,
@ProtoId(4) val vNotifyCookie: ByteArray? = EMPTY_BYTE_ARRAY,
@ProtoId(5) val usMsgType: Int?,
@ProtoId(6) val wUserActive: Int?,
@ProtoId(7) val wGeneralFlag: Int?,
@ProtoId(8) val bindedUin: Long?,
@ProtoId(9) val stMsgInfo: MsgInfo?,
@ProtoId(10) val msgCtrlBuf: String?,
@ProtoId(11) val serverBuf: ByteArray?,
@ProtoId(12) val pingFlag: Long?,
@ProtoId(13) val svrip: Int?
@JceId(0) val uin: Long? = 0L,
@JceId(1) val ctype: Byte = 0,
@JceId(2) val strService: String?,
@JceId(3) val strCmd: String?,
@JceId(4) val vNotifyCookie: ByteArray? = EMPTY_BYTE_ARRAY,
@JceId(5) val usMsgType: Int?,
@JceId(6) val wUserActive: Int?,
@JceId(7) val wGeneralFlag: Int?,
@JceId(8) val bindedUin: Long?,
@JceId(9) val stMsgInfo: MsgInfo?,
@JceId(10) val msgCtrlBuf: String?,
@JceId(11) val serverBuf: ByteArray?,
@JceId(12) val pingFlag: Long?,
@JceId(13) val svrip: Int?
) : JceStruct, Packet
@Serializable
internal class MsgInfo(
@ProtoId(0) val lFromUin: Long? = 0L,
@ProtoId(1) val uMsgTime: Long? = 0L,
@ProtoId(2) val shMsgType: Short,
@ProtoId(3) val shMsgSeq: Short,
@ProtoId(4) val strMsg: String?,
@ProtoId(5) val uRealMsgTime: Int?,
@ProtoId(6) val vMsg: ByteArray?,
@ProtoId(7) val uAppShareID: Long?,
@ProtoId(8) val vMsgCookies: ByteArray? = EMPTY_BYTE_ARRAY,
@ProtoId(9) val vAppShareCookie: ByteArray? = EMPTY_BYTE_ARRAY,
@ProtoId(10) val lMsgUid: Long?,
@ProtoId(11) val lLastChangeTime: Long?,
@ProtoId(12) val vCPicInfo: List<CPicInfo>?,
@ProtoId(13) val stShareData: ShareData?,
@ProtoId(14) val lFromInstId: Long?,
@ProtoId(15) val vRemarkOfSender: ByteArray?,
@ProtoId(16) val strFromMobile: String?,
@ProtoId(17) val strFromName: String?,
@ProtoId(18) val vNickName: List<String>?//,
@JceId(0) val lFromUin: Long? = 0L,
@JceId(1) val uMsgTime: Long? = 0L,
@JceId(2) val shMsgType: Short,
@JceId(3) val shMsgSeq: Short,
@JceId(4) val strMsg: String?,
@JceId(5) val uRealMsgTime: Int?,
@JceId(6) val vMsg: ByteArray?,
@JceId(7) val uAppShareID: Long?,
@JceId(8) val vMsgCookies: ByteArray? = EMPTY_BYTE_ARRAY,
@JceId(9) val vAppShareCookie: ByteArray? = EMPTY_BYTE_ARRAY,
@JceId(10) val lMsgUid: Long?,
@JceId(11) val lLastChangeTime: Long?,
@JceId(12) val vCPicInfo: List<CPicInfo>?,
@JceId(13) val stShareData: ShareData?,
@JceId(14) val lFromInstId: Long?,
@JceId(15) val vRemarkOfSender: ByteArray?,
@JceId(16) val strFromMobile: String?,
@JceId(17) val strFromName: String?,
@JceId(18) val vNickName: List<String>?//,
//@SerialId(19) val stC2CTmpMsgHead: TempMsgHead?
) : JceStruct
@Serializable
internal class ShareData(
@ProtoId(0) val pkgname: String = "",
@ProtoId(1) val msgtail: String = "",
@ProtoId(2) val picurl: String = "",
@ProtoId(3) val url: String = ""
@JceId(0) val pkgname: String = "",
@JceId(1) val msgtail: String = "",
@JceId(2) val picurl: String = "",
@JceId(3) val url: String = ""
) : JceStruct
@Serializable
internal class TempMsgHead(
@ProtoId(0) val c2c_type: Int? = 0,
@ProtoId(1) val serviceType: Int? = 0
@JceId(0) val c2c_type: Int? = 0,
@JceId(1) val serviceType: Int? = 0
) : JceStruct
@Serializable
internal class CPicInfo(
@ProtoId(0) val vPath: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(1) val vHost: ByteArray? = EMPTY_BYTE_ARRAY
@JceId(0) val vPath: ByteArray = EMPTY_BYTE_ARRAY,
@JceId(1) val vHost: ByteArray? = EMPTY_BYTE_ARRAY
) : JceStruct
\ No newline at end of file
......@@ -10,37 +10,37 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.jce
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
private val EMPTY_MAP = mapOf<String, String>()
@Serializable
internal class RequestPacket(
@ProtoId(1) val iVersion: Short? = 3,
@ProtoId(2) val cPacketType: Byte = 0,
@ProtoId(3) val iMessageType: Int = 0,
@ProtoId(4) val iRequestId: Int,
@ProtoId(5) val sServantName: String = "",
@ProtoId(6) val sFuncName: String = "",
@ProtoId(7) val sBuffer: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoId(8) val iTimeout: Int? = 0,
@ProtoId(9) val context: Map<String, String>? = EMPTY_MAP,
@ProtoId(10) val status: Map<String, String>? = EMPTY_MAP
@JceId(1) val iVersion: Short? = 3,
@JceId(2) val cPacketType: Byte = 0,
@JceId(3) val iMessageType: Int = 0,
@JceId(4) val iRequestId: Int,
@JceId(5) val sServantName: String = "",
@JceId(6) val sFuncName: String = "",
@JceId(7) val sBuffer: ByteArray = EMPTY_BYTE_ARRAY,
@JceId(8) val iTimeout: Int? = 0,
@JceId(9) val context: Map<String, String>? = EMPTY_MAP,
@JceId(10) val status: Map<String, String>? = EMPTY_MAP
) : JceStruct
@Serializable
internal class RequestDataVersion3(
@ProtoId(0) val map: Map<String, ByteArray> // 注意: ByteArray 不能直接放序列化的 JceStruct!! 要放类似 RequestDataStructSvcReqRegister 的
@JceId(0) val map: Map<String, ByteArray> // 注意: ByteArray 不能直接放序列化的 JceStruct!! 要放类似 RequestDataStructSvcReqRegister 的
) : JceStruct
@Serializable
internal class RequestDataVersion2(
@ProtoId(0) val map: Map<String, Map<String, ByteArray>>
@JceId(0) val map: Map<String, Map<String, ByteArray>>
) : JceStruct
@Serializable
internal class RequestDataStructSvcReqRegister(
@ProtoId(0) val struct: SvcReqRegister
@JceId(0) val struct: SvcReqRegister
) : JceStruct
\ No newline at end of file
......@@ -12,11 +12,12 @@ package net.mamoe.mirai.qqandroid.network.protocol.data.jce
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
@Serializable
internal class RequestPushForceOffline(
@ProtoId(0) val uin: Long,
@ProtoId(1) val title: String? = "",
@ProtoId(2) val tips: String? = "",
@ProtoId(3) val sameDevice: Byte? = null
@JceId(0) val uin: Long,
@JceId(1) val title: String? = "",
@JceId(2) val tips: String? = "",
@JceId(3) val sameDevice: Byte? = null
) : JceStruct
\ No newline at end of file
......@@ -10,46 +10,46 @@
package net.mamoe.mirai.qqandroid.network.protocol.data.jce
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoId
import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.serialization.jce.JceId
@Serializable
internal class SvcReqRegister(
@ProtoId(0) val lUin: Long = 0L,
@ProtoId(1) val lBid: Long = 0L,
@ProtoId(2) val cConnType: Byte = 0,
@ProtoId(3) val sOther: String = "",
@ProtoId(4) val iStatus: Int = 11,
@ProtoId(5) val bOnlinePush: Byte = 0,
@ProtoId(6) val bIsOnline: Byte = 0,
@ProtoId(7) val bIsShowOnline: Byte = 0,
@ProtoId(8) val bKikPC: Byte = 0,
@ProtoId(9) val bKikWeak: Byte = 0,
@ProtoId(10) val timeStamp: Long = 0L,
@ProtoId(11) val iOSVersion: Long = 0L,
@ProtoId(12) val cNetType: Byte = 0,
@ProtoId(13) val sBuildVer: String? = "",
@ProtoId(14) val bRegType: Byte = 0,
@ProtoId(15) val vecDevParam: ByteArray? = null,
@ProtoId(16) val vecGuid: ByteArray? = null,
@ProtoId(17) val iLocaleID: Int = 2052,
@ProtoId(18) val bSlientPush: Byte = 0,
@ProtoId(19) val strDevName: String? = null,
@ProtoId(20) val strDevType: String? = null,
@ProtoId(21) val strOSVer: String? = null,
@ProtoId(22) val bOpenPush: Byte = 1,
@ProtoId(23) val iLargeSeq: Long = 0L,
@ProtoId(24) val iLastWatchStartTime: Long = 0L,
@ProtoId(26) val uOldSSOIp: Long = 0L,
@ProtoId(27) val uNewSSOIp: Long = 0L,
@ProtoId(28) val sChannelNo: String? = null,
@ProtoId(29) val lCpId: Long = 0L,
@ProtoId(30) val strVendorName: String? = null,
@ProtoId(31) val strVendorOSName: String? = null,
@ProtoId(32) val strIOSIdfa: String? = null,
@ProtoId(33) val bytes_0x769_reqbody: ByteArray? = null,
@ProtoId(34) val bIsSetStatus: Byte = 0,
@ProtoId(35) val vecServerBuf: ByteArray? = null,
@ProtoId(36) val bSetMute: Byte = 0
@JceId(0) val lUin: Long = 0L,
@JceId(1) val lBid: Long = 0L,
@JceId(2) val cConnType: Byte = 0,
@JceId(3) val sOther: String = "",
@JceId(4) val iStatus: Int = 11,
@JceId(5) val bOnlinePush: Byte = 0,
@JceId(6) val bIsOnline: Byte = 0,
@JceId(7) val bIsShowOnline: Byte = 0,
@JceId(8) val bKikPC: Byte = 0,
@JceId(9) val bKikWeak: Byte = 0,
@JceId(10) val timeStamp: Long = 0L,
@JceId(11) val iOSVersion: Long = 0L,
@JceId(12) val cNetType: Byte = 0,
@JceId(13) val sBuildVer: String? = "",
@JceId(14) val bRegType: Byte = 0,
@JceId(15) val vecDevParam: ByteArray? = null,
@JceId(16) val vecGuid: ByteArray? = null,
@JceId(17) val iLocaleID: Int = 2052,
@JceId(18) val bSlientPush: Byte = 0,
@JceId(19) val strDevName: String? = null,
@JceId(20) val strDevType: String? = null,
@JceId(21) val strOSVer: String? = null,
@JceId(22) val bOpenPush: Byte = 1,
@JceId(23) val iLargeSeq: Long = 0L,
@JceId(24) val iLastWatchStartTime: Long = 0L,
@JceId(26) val uOldSSOIp: Long = 0L,
@JceId(27) val uNewSSOIp: Long = 0L,
@JceId(28) val sChannelNo: String? = null,
@JceId(29) val lCpId: Long = 0L,
@JceId(30) val strVendorName: String? = null,
@JceId(31) val strVendorOSName: String? = null,
@JceId(32) val strIOSIdfa: String? = null,
@JceId(33) val bytes_0x769_reqbody: ByteArray? = null,
@JceId(34) val bIsSetStatus: Byte = 0,
@JceId(35) val vecServerBuf: ByteArray? = null,
@JceId(36) val bSetMute: Byte = 0
// @SerialId(25) var vecBindUin: ArrayList<*>? = null // ?? 未知泛型
) : JceStruct
\ No newline at end of file
......@@ -6,9 +6,9 @@ import kotlinx.io.core.buildPacket
import kotlinx.io.core.writeFully
import kotlinx.serialization.MissingFieldException
import kotlinx.serialization.Serializable
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.JceNew
import net.mamoe.mirai.qqandroid.io.serialization.jce.writeJceHead
import kotlin.test.Test
import kotlin.test.assertEquals
......@@ -98,7 +98,7 @@ internal class JceInputTest {
to TestSerializableClassC(123123)
)
),
JceNew.UTF_8.load(TestSerializableClassA.serializer(), input)
Jce.UTF_8.load(TestSerializableClassA.serializer(), input)
)
}
......@@ -155,7 +155,7 @@ internal class JceInputTest {
5,
TestSerializableClassB(123, TestSerializableClassC(123123), 9)
),
JceNew.UTF_8.load(TestSerializableClassA.serializer(), input)
Jce.UTF_8.load(TestSerializableClassA.serializer(), input)
)
}
......@@ -194,7 +194,7 @@ internal class JceInputTest {
}
}
assertEquals(TestSerializableClassA(), JceNew.UTF_8.load(TestSerializableClassA.serializer(), input))
assertEquals(TestSerializableClassA(), Jce.UTF_8.load(TestSerializableClassA.serializer(), input))
}
@Test
......@@ -232,7 +232,70 @@ internal class JceInputTest {
assertEquals(
TestSerializableClassA(mapOf(1 to 2, 33 to 44)),
JceNew.UTF_8.load(TestSerializableClassA.serializer(), input)
Jce.UTF_8.load(TestSerializableClassA.serializer(), input)
)
}
@Test
fun testMapStringInt() {
@Serializable
data class TestSerializableClassA(
@JceId(0) val byteArray: Map<String, Int>
)
val input = buildPacket {
writeJceHead(MAP, 0)
mapOf("str1" to 2, "str2" to 44).let {
writeJceHead(BYTE, 0)
writeByte(it.size.toByte())
it.forEach { (key, value) ->
writeJceHead(STRING1, 0)
writeByte(key.length.toByte())
writeStringUtf8(key)
writeJceHead(INT, 1)
writeInt(value)
}
}
}
assertEquals(
TestSerializableClassA(mapOf("str1" to 2, "str2" to 44)),
Jce.UTF_8.load(TestSerializableClassA.serializer(), input)
)
}
@Test
fun testMapStringByteArray() {
@Serializable
data class TestSerializableClassA(
@JceId(0) val byteArray: Map<String, ByteArray>
)
val input = buildPacket {
writeJceHead(MAP, 0)
mapOf("str1" to byteArrayOf(2, 3, 4), "str2" to byteArrayOf(2, 3, 4)).let {
writeJceHead(BYTE, 0)
writeByte(it.size.toByte())
it.forEach { (key, value) ->
writeJceHead(STRING1, 0)
writeByte(key.length.toByte())
writeStringUtf8(key)
writeJceHead(SIMPLE_LIST, 1)
writeJceHead(BYTE, 0)
writeFully(value)
}
}
}
assertEquals(
TestSerializableClassA(mapOf("str1" to byteArrayOf(2, 3, 4), "str2" to byteArrayOf(2, 3, 4))),
Jce.UTF_8.load(TestSerializableClassA.serializer(), input)
)
}
......@@ -282,7 +345,7 @@ internal class JceInputTest {
}
}
assertEquals(TestSerializableClassA(), JceNew.UTF_8.load(TestSerializableClassA.serializer(), input))
assertEquals(TestSerializableClassA(), Jce.UTF_8.load(TestSerializableClassA.serializer(), input))
}
......@@ -319,7 +382,7 @@ internal class JceInputTest {
writeByte(1) // boolean
}
assertEquals(TestSerializableClassA(), JceNew.UTF_8.load(TestSerializableClassA.serializer(), input))
assertEquals(TestSerializableClassA(), Jce.UTF_8.load(TestSerializableClassA.serializer(), input))
}
@Test
......@@ -338,7 +401,7 @@ internal class JceInputTest {
writeShort(123)
}
assertFailsWith<MissingFieldException> { JceNew.UTF_8.load(TestSerializableClassA.serializer(), input) }
assertFailsWith<MissingFieldException> { Jce.UTF_8.load(TestSerializableClassA.serializer(), input) }
}
@Test
......
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