Commit 2f9d104f authored by Him188's avatar Him188

Jce Serialization optional elements support

parent d47bd11d
...@@ -55,7 +55,7 @@ kotlin { ...@@ -55,7 +55,7 @@ kotlin {
sourceSets.all { sourceSets.all {
languageSettings.enableLanguageFeature("InlineClasses") languageSettings.enableLanguageFeature("InlineClasses")
languageSettings.enableLanguageFeature("NewInference")
languageSettings.useExperimentalAnnotation("kotlin.Experimental") languageSettings.useExperimentalAnnotation("kotlin.Experimental")
dependencies { dependencies {
......
...@@ -58,7 +58,7 @@ kotlin { ...@@ -58,7 +58,7 @@ kotlin {
sourceSets { sourceSets {
all { all {
languageSettings.enableLanguageFeature("InlineClasses") languageSettings.enableLanguageFeature("InlineClasses")
languageSettings.enableLanguageFeature("NewInference")
languageSettings.useExperimentalAnnotation("kotlin.Experimental") languageSettings.useExperimentalAnnotation("kotlin.Experimental")
dependencies { dependencies {
......
...@@ -8,7 +8,6 @@ import net.mamoe.mirai.qqandroid.io.JceStruct ...@@ -8,7 +8,6 @@ import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
private val EMPTY_MAP = mapOf<String, String>() private val EMPTY_MAP = mapOf<String, String>()
private val EMPTY_SBUFFER_MAP = mapOf<Int, ByteArray>()
@Serializable @Serializable
class RequestPacket( class RequestPacket(
......
...@@ -34,11 +34,11 @@ class SvcReqRegister( ...@@ -34,11 +34,11 @@ class SvcReqRegister(
@SerialId(24) val iLastWatchStartTime: Long = 0L, @SerialId(24) val iLastWatchStartTime: Long = 0L,
@SerialId(26) val uOldSSOIp: Long = 0L, @SerialId(26) val uOldSSOIp: Long = 0L,
@SerialId(27) val uNewSSOIp: Long = 0L, @SerialId(27) val uNewSSOIp: Long = 0L,
@SerialId(28) val sChannelNo: String? = "", @SerialId(28) val sChannelNo: String? = null,
@SerialId(29) val lCpId: Long = 0L, @SerialId(29) val lCpId: Long = 0L,
@SerialId(30) val strVendorName: String? = null, @SerialId(30) val strVendorName: String? = null,
@SerialId(31) val strVendorOSName: String? = null, @SerialId(31) val strVendorOSName: String? = null,
@SerialId(32) val strIOSIdfa: String? = "", @SerialId(32) val strIOSIdfa: String? = null,
@SerialId(33) val bytes_0x769_reqbody: ByteArray? = null, @SerialId(33) val bytes_0x769_reqbody: ByteArray? = null,
@SerialId(34) val bIsSetStatus: Byte = 0, @SerialId(34) val bIsSetStatus: Byte = 0,
@SerialId(35) val vecServerBuf: ByteArray? = null, @SerialId(35) val vecServerBuf: ByteArray? = null,
......
...@@ -250,7 +250,7 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf( ...@@ -250,7 +250,7 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
private suspend fun ByteReadPacket.parseUniResponse(bot: QQAndroidBot, packetFactory: PacketFactory<*>, ssoSequenceId: Int, consumer: PacketConsumer) { private suspend fun ByteReadPacket.parseUniResponse(bot: QQAndroidBot, packetFactory: PacketFactory<*>, ssoSequenceId: Int, consumer: PacketConsumer) {
val uni = readBytes(readInt() - 4).loadAs(RequestPacket.serializer()) val uni = readBytes(readInt() - 4).loadAs(RequestPacket.serializer())
PacketLogger.verbose(uni.toString()) PacketLogger.verbose(uni.toString())
consumer(packetFactory.decode(bot, uni.sBuffer.toReadPacket()), uni.sServantName + "." + uni.sFuncName, ssoSequenceId) /// consumer(packetFactory.decode(bot, uni.sBuffer.toReadPacket()), uni.sServantName + "." + uni.sFuncName, ssoSequenceId)
} }
} }
......
...@@ -12,7 +12,7 @@ internal class RequestPushNotify( ...@@ -12,7 +12,7 @@ internal class RequestPushNotify(
@SerialId(1) val ctype: Byte = 0, @SerialId(1) val ctype: Byte = 0,
@SerialId(2) val strService: String?, @SerialId(2) val strService: String?,
@SerialId(3) val strCmd: String?, @SerialId(3) val strCmd: String?,
@SerialId(4) val vNotifyCookie: ByteArray = EMPTY_BYTE_ARRAY, @SerialId(4) val vNotifyCookie: ByteArray? = EMPTY_BYTE_ARRAY,
@SerialId(5) val usMsgType: Int?, @SerialId(5) val usMsgType: Int?,
@SerialId(6) val wUserActive: Int?, @SerialId(6) val wUserActive: Int?,
@SerialId(7) val wGeneralFlag: Int?, @SerialId(7) val wGeneralFlag: Int?,
...@@ -28,14 +28,14 @@ internal class RequestPushNotify( ...@@ -28,14 +28,14 @@ internal class RequestPushNotify(
internal class MsgInfo( internal class MsgInfo(
@SerialId(0) val lFromUin: Long = 0L, @SerialId(0) val lFromUin: Long = 0L,
@SerialId(1) val uMsgTime: Long = 0L, @SerialId(1) val uMsgTime: Long = 0L,
@SerialId(2) val shMsgType: Short?, @SerialId(2) val shMsgType: Short,
@SerialId(3) val shMsgSeq: Short?, @SerialId(3) val shMsgSeq: Short,
@SerialId(4) val strMsg: String?, @SerialId(4) val strMsg: String?,
@SerialId(5) val uRealMsgTime: Int?, @SerialId(5) val uRealMsgTime: Int?,
@SerialId(6) val vMsg: ByteArray?, @SerialId(6) val vMsg: ByteArray?,
@SerialId(7) val uAppShareID: Long?, @SerialId(7) val uAppShareID: Long?,
@SerialId(8) val vMsgCookies: ByteArray = EMPTY_BYTE_ARRAY, @SerialId(8) val vMsgCookies: ByteArray? = EMPTY_BYTE_ARRAY,
@SerialId(9) val vAppShareCookie: ByteArray = EMPTY_BYTE_ARRAY, @SerialId(9) val vAppShareCookie: ByteArray? = EMPTY_BYTE_ARRAY,
@SerialId(10) val lMsgUid: Long?, @SerialId(10) val lMsgUid: Long?,
@SerialId(11) val lLastChangeTime: Long?, @SerialId(11) val lLastChangeTime: Long?,
@SerialId(12) val vCPicInfo: List<CPicInfo>?, @SerialId(12) val vCPicInfo: List<CPicInfo>?,
...@@ -59,12 +59,12 @@ class ShareData( ...@@ -59,12 +59,12 @@ class ShareData(
@Serializable @Serializable
class TempMsgHead( class TempMsgHead(
@SerialId(0) val c2c_type: Int = 0, @SerialId(0) val c2c_type: Int? = 0,
@SerialId(1) val serviceType: Int = 0 @SerialId(1) val serviceType: Int? = 0
) : JceStruct ) : JceStruct
@Serializable @Serializable
class CPicInfo( class CPicInfo(
@SerialId(0) val vPath: ByteArray = EMPTY_BYTE_ARRAY, @SerialId(0) val vPath: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(1) val vHost: ByteArray = EMPTY_BYTE_ARRAY @SerialId(1) val vHost: ByteArray? = EMPTY_BYTE_ARRAY
) : JceStruct ) : JceStruct
\ No newline at end of file
...@@ -2,31 +2,39 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive ...@@ -2,31 +2,39 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact import kotlinx.io.core.discardExact
import kotlinx.serialization.protobuf.ProtoBuf import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.io.serialization.Jce import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.serialization.loadAs import net.mamoe.mirai.qqandroid.io.serialization.loadAs
import net.mamoe.mirai.qqandroid.io.serialization.readRemainingAsJceStruct
import net.mamoe.mirai.qqandroid.network.protocol.jce.RequestDataVersion2 import net.mamoe.mirai.qqandroid.network.protocol.jce.RequestDataVersion2
import net.mamoe.mirai.qqandroid.network.protocol.jce.RequestDataVersion3
import net.mamoe.mirai.qqandroid.network.protocol.jce.RequestPacket import net.mamoe.mirai.qqandroid.network.protocol.jce.RequestPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.RequestPushNotify import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.RequestPushNotify
import net.mamoe.mirai.utils.cryptor.contentToString import net.mamoe.mirai.utils.cryptor.contentToString
import net.mamoe.mirai.utils.io.readRemainingBytes import net.mamoe.mirai.utils.firstValue
import net.mamoe.mirai.utils.io.debugPrint
import net.mamoe.mirai.utils.io.toReadPacket
import net.mamoe.mirai.utils.io.toUHexString
class MessageSvc { class MessageSvc {
internal object PushNotify : PacketFactory<RequestPushNotify>("MessageSvc.PushNotify") { internal object PushNotify : PacketFactory<RequestPushNotify>("MessageSvc.PushNotify") {
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): RequestPushNotify { override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): RequestPushNotify {
val req = Jce.UTF8.load( discardExact(8)
RequestPacket.serializer(),
this.apply { discardExact(8) }.readRemainingBytes() @Serializable
) class ResponseDataRequestPushNotify(
val messageNotification = Jce.UTF8.load( @SerialId(0) val notify: RequestPushNotify
RequestPushNotify.serializer(), ) : JceStruct
req.sBuffer.loadAs(RequestDataVersion2.serializer()).map.entries.first().value.entries.first().value
) val requestPushNotify = readRemainingAsJceStruct(RequestPacket.serializer()).sBuffer
println(messageNotification.contentToString()) .loadAs(RequestDataVersion2.serializer()).map.firstValue().firstValue()
ProtoBuf .toReadPacket().apply { discardExact(1) }
.debugPrint()
.readRemainingAsJceStruct(RequestPushNotify.serializer())
println(requestPushNotify.contentToString())
TODO() TODO()
} }
} }
......
package net.mamoe.mirai.qqandroid.network.protocol.packet.login package net.mamoe.mirai.qqandroid.network.protocol.packet.login
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.writeFully
import kotlinx.serialization.protobuf.ProtoBuf import kotlinx.serialization.protobuf.ProtoBuf
import net.mamoe.mirai.data.Packet import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.io.serialization.toByteArray import net.mamoe.mirai.qqandroid.io.serialization.toByteArray
import net.mamoe.mirai.qqandroid.io.serialization.writeJceStruct
import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.jce.RequestDataStructSvcReqRegister import net.mamoe.mirai.qqandroid.network.protocol.jce.RequestDataStructSvcReqRegister
import net.mamoe.mirai.qqandroid.network.protocol.jce.RequestDataVersion3 import net.mamoe.mirai.qqandroid.network.protocol.jce.RequestDataVersion3
...@@ -56,7 +56,8 @@ class StatSvc { ...@@ -56,7 +56,8 @@ class StatSvc {
client, subAppId = subAppId, commandName = commandName, client, subAppId = subAppId, commandName = commandName,
extraData = client.wLoginSigInfo.tgt.toReadPacket(), sequenceId = sequenceId extraData = client.wLoginSigInfo.tgt.toReadPacket(), sequenceId = sequenceId
) { ) {
writeFully( writeJceStruct(
RequestPacket.serializer(),
RequestPacket( RequestPacket(
sServantName = "PushService", sServantName = "PushService",
sFuncName = "SvcReqRegister", sFuncName = "SvcReqRegister",
...@@ -121,7 +122,7 @@ class StatSvc { ...@@ -121,7 +122,7 @@ class StatSvc {
).toByteArray(RequestDataStructSvcReqRegister.serializer()) ).toByteArray(RequestDataStructSvcReqRegister.serializer())
) )
).toByteArray(RequestDataVersion3.serializer()) ).toByteArray(RequestDataVersion3.serializer())
).toByteArray(RequestPacket.serializer()) )
) )
} }
} }
......
...@@ -2,6 +2,7 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769 ...@@ -2,6 +2,7 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769
import kotlinx.serialization.SerialId import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.network.protocol.protobuf.ProtoBuf
class Oidb0x769 { class Oidb0x769 {
@Serializable @Serializable
...@@ -13,19 +14,19 @@ class Oidb0x769 { ...@@ -13,19 +14,19 @@ class Oidb0x769 {
// @SerialId(5) val city: String, // @SerialId(5) val city: String,
// @SerialId(6) val req_debug_msg: Int = 0, // @SerialId(6) val req_debug_msg: Int = 0,
// @SerialId(101) val query_uin_package_usage_req: QueryUinPackageUsageReq // @SerialId(101) val query_uin_package_usage_req: QueryUinPackageUsageReq
) ) : ProtoBuf
@Serializable @Serializable
class QueryUinPackageUsageReq( class QueryUinPackageUsageReq(
@SerialId(1) val type: Int, @SerialId(1) val type: Int,
@SerialId(2) val uinFileSize: Long = 0 @SerialId(2) val uinFileSize: Long = 0
) ): ProtoBuf
@Serializable @Serializable
class ConfigSeq( class ConfigSeq(
@SerialId(1) val type: Int, // uint @SerialId(1) val type: Int, // uint
@SerialId(2) val version: Int // uint @SerialId(2) val version: Int // uint
) ): ProtoBuf
@Serializable @Serializable
class DeviceInfo( class DeviceInfo(
...@@ -37,7 +38,7 @@ class Oidb0x769 { ...@@ -37,7 +38,7 @@ class Oidb0x769 {
//@SerialId(6) val storage: Storage, //@SerialId(6) val storage: Storage,
//@SerialId(7) val screen: Screen, //@SerialId(7) val screen: Screen,
//@SerialId(8) val camera: Camera //@SerialId(8) val camera: Camera
) ): ProtoBuf
@Serializable @Serializable
class OS( class OS(
...@@ -46,27 +47,27 @@ class Oidb0x769 { ...@@ -46,27 +47,27 @@ class Oidb0x769 {
@SerialId(3) val sdk: String, @SerialId(3) val sdk: String,
@SerialId(4) val kernel: String, @SerialId(4) val kernel: String,
@SerialId(5) val rom: String @SerialId(5) val rom: String
) ): ProtoBuf
@Serializable @Serializable
class Camera( class Camera(
@SerialId(1) val primary: Long, @SerialId(1) val primary: Long,
@SerialId(2) val secondary: Long, @SerialId(2) val secondary: Long,
@SerialId(3) val flag: Boolean @SerialId(3) val flag: Boolean
) ): ProtoBuf
@Serializable @Serializable
class CPU( class CPU(
@SerialId(1) val model: String, @SerialId(1) val model: String,
@SerialId(2) val frequency: Int, @SerialId(2) val frequency: Int,
@SerialId(3) val cores: Int @SerialId(3) val cores: Int
) ): ProtoBuf
@Serializable @Serializable
class Memory( class Memory(
@SerialId(1) val total: Int, @SerialId(1) val total: Int,
@SerialId(2) val process: Int @SerialId(2) val process: Int
) ): ProtoBuf
@Serializable @Serializable
class Screen( class Screen(
...@@ -75,11 +76,11 @@ class Oidb0x769 { ...@@ -75,11 +76,11 @@ class Oidb0x769 {
@SerialId(3) val height: Int, @SerialId(3) val height: Int,
@SerialId(4) val dpi: Int, @SerialId(4) val dpi: Int,
@SerialId(5) val multiTouch: Boolean @SerialId(5) val multiTouch: Boolean
) ): ProtoBuf
@Serializable @Serializable
class Storage( class Storage(
@SerialId(1) val builtin: Int, @SerialId(1) val builtin: Int,
@SerialId(2) val external: Int @SerialId(2) val external: Int
) ): ProtoBuf
} }
\ No newline at end of file
...@@ -7,9 +7,7 @@ import net.mamoe.mirai.qqandroid.io.JceOutput ...@@ -7,9 +7,7 @@ import net.mamoe.mirai.qqandroid.io.JceOutput
import net.mamoe.mirai.qqandroid.io.JceStruct import net.mamoe.mirai.qqandroid.io.JceStruct
import net.mamoe.mirai.qqandroid.io.buildJcePacket import net.mamoe.mirai.qqandroid.io.buildJcePacket
import net.mamoe.mirai.utils.cryptor.contentToString import net.mamoe.mirai.utils.cryptor.contentToString
import net.mamoe.mirai.utils.io.toUHexString
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals
fun main() { fun main() {
JceDecoderTest().testSimpleMap() JceDecoderTest().testSimpleMap()
...@@ -41,7 +39,8 @@ class JceDecoderTest { ...@@ -41,7 +39,8 @@ class JceDecoderTest {
@Serializable @Serializable
class TestComplexJceStruct( class TestComplexJceStruct(
@SerialId(7) val byteArray: ByteArray = byteArrayOf(1, 2, 3), @SerialId(6) val string: String = "haha",
@SerialId(7) val byteArray: ByteArray = ByteArray(2000),
@SerialId(8) val byteList: List<Byte> = listOf(1, 2, 3), // error here @SerialId(8) val byteList: List<Byte> = listOf(1, 2, 3), // error here
@SerialId(9) val map: Map<String, Map<String, ByteArray>> = mapOf("哈哈" to mapOf("哈哈" to byteArrayOf(1, 2, 3))), @SerialId(9) val map: Map<String, Map<String, ByteArray>> = mapOf("哈哈" to mapOf("哈哈" to byteArrayOf(1, 2, 3))),
// @SerialId(10) val nestedJceStruct: TestSimpleJceStruct = TestSimpleJceStruct(), // @SerialId(10) val nestedJceStruct: TestSimpleJceStruct = TestSimpleJceStruct(),
...@@ -50,10 +49,11 @@ class JceDecoderTest { ...@@ -50,10 +49,11 @@ class JceDecoderTest {
@Serializable @Serializable
class TestComplexNullableJceStruct( class TestComplexNullableJceStruct(
@SerialId(7) val byteArray: ByteArray? = byteArrayOf(1, 2, 3), @SerialId(6) val string: String = "haha",
@SerialId(7) val byteArray: ByteArray = ByteArray(2000),
@SerialId(8) val byteList: List<Byte>? = listOf(1, 2, 3), // error here @SerialId(8) val byteList: List<Byte>? = listOf(1, 2, 3), // error here
@SerialId(9) val map: Map<String, Map<String, ByteArray>>? = mapOf("哈哈" to mapOf("哈哈" to byteArrayOf(1, 2, 3))), @SerialId(9) val map: Map<String, Map<String, ByteArray>>? = mapOf("哈哈" to mapOf("哈哈" to byteArrayOf(1, 2, 3))),
@SerialId(10) val nestedJceStruct: TestSimpleJceStruct? = TestSimpleJceStruct(), @SerialId(10) val nestedJceStruct: TestComplexJceStruct? = TestComplexJceStruct(),
@SerialId(11) val byteList2: List<List<Int>>? = listOf(listOf(1, 2, 3), listOf(1, 2, 3)) @SerialId(11) val byteList2: List<List<Int>>? = listOf(listOf(1, 2, 3), listOf(1, 2, 3))
) : JceStruct ) : JceStruct
...@@ -63,20 +63,10 @@ class JceDecoderTest { ...@@ -63,20 +63,10 @@ class JceDecoderTest {
} }
@Test @Test
fun testEncoder2() { fun testEncoder3() {
assertEquals( println(TestComplexNullableJceStruct().toByteArray(TestComplexNullableJceStruct.serializer()).loadAs(TestComplexNullableJceStruct.serializer()).contentToString())
buildJcePacket {
writeFully(byteArrayOf(1, 2, 3), 7)
writeCollection(listOf(1, 2, 3), 8)
writeMap(mapOf("哈哈" to mapOf("哈哈" to byteArrayOf(1, 2, 3))), 9)
writeJceStruct(TestSimpleJceStruct(), 10)
writeCollection(listOf(listOf(1, 2, 3), listOf(1, 2, 3)), 11)
}.readBytes().toUHexString(),
TestComplexNullableJceStruct().toByteArray(TestComplexNullableJceStruct.serializer()).toUHexString()
)
} }
@Test @Test
fun testNestedList() { fun testNestedList() {
@Serializable @Serializable
...@@ -133,6 +123,6 @@ class JceDecoderTest { ...@@ -133,6 +123,6 @@ class JceDecoderTest {
) )
println(buildJcePacket { println(buildJcePacket {
writeMap(mapOf(byteArrayOf(1) to mapOf(byteArrayOf(1) to shortArrayOf(2))), 7) writeMap(mapOf(byteArrayOf(1) to mapOf(byteArrayOf(1) to shortArrayOf(2))), 7)
}.readBytes().loadAs(TestNestedMap.serializer()).map.entries.first().value!!.contentToString()) }.readBytes().loadAs(TestNestedMap.serializer()).map.entries.first().value.contentToString())
} }
} }
\ No newline at end of file
package net.mamoe.mirai.qqandroid.io.serialization
import net.mamoe.mirai.qqandroid.network.protocol.jce.RequestPacket
import net.mamoe.mirai.utils.io.hexToBytes
class TestRequesetPacket {
companion object {
@JvmStatic
fun main(args: Array<String>) {
val data =
"10 03 2C 3C 4C 56 0B 50 75 73 68 53 65 72 76 69 63 65 66 0E 53 76 63 52 65 71 52 65 67 69 73 74 65 72 7D 00 01 D6 00 08 00 01 06 0E 53 76 63 52 65 71 52 65 67 69 73 74 65 72 1D 00 01 BE 00 0A 02 DD B8 E4 76 10 07 2C 36 00 40 0B 5C 6C 7C 8C 9C AC B0 1D C0 01 D6 00 EC FD 10 00 00 10 07 EA 76 78 FD EB 06 C3 33 B2 18 80 32 15 09 BA F1 11 04 08 FC 12 F6 13 19 41 6E 64 72 6F 69 64 20 53 44 4B 20 62 75 69 6C 74 20 66 6F 72 20 78 38 36 F6 14 19 41 6E 64 72 6F 69 64 20 53 44 4B 20 62 75 69 6C 74 20 66 6F 72 20 78 38 36 F6 15 02 31 30 F0 16 01 F1 17 0F 06 FC 18 FC 1A F3 1B A9 00 FE 00 66 00 82 00 FC 1D F6 1E 04 4D 49 55 49 F6 1F 14 3F 4F 4E 45 50 4C 55 53 20 41 35 30 30 30 5F 32 33 5F 31 37 FD 21 00 00 0D 0A 04 08 2E 10 00 0A 05 08 9B 02 10 00 FC 22 FC 24 0B 8C 98 0C A8 0C".hexToBytes()
println(data.loadAs(RequestPacket.serializer(), JceCharset.UTF8))
}
}
}
\ No newline at end of file
...@@ -58,7 +58,7 @@ kotlin { ...@@ -58,7 +58,7 @@ kotlin {
sourceSets { sourceSets {
all { all {
languageSettings.enableLanguageFeature("InlineClasses") languageSettings.enableLanguageFeature("InlineClasses")
languageSettings.enableLanguageFeature("NewInference")
languageSettings.useExperimentalAnnotation("kotlin.Experimental") languageSettings.useExperimentalAnnotation("kotlin.Experimental")
dependencies { dependencies {
......
...@@ -57,7 +57,7 @@ kotlin { ...@@ -57,7 +57,7 @@ kotlin {
sourceSets { sourceSets {
all { all {
languageSettings.enableLanguageFeature("InlineClasses") languageSettings.enableLanguageFeature("InlineClasses")
languageSettings.enableLanguageFeature("NewInference")
languageSettings.useExperimentalAnnotation("kotlin.Experimental") languageSettings.useExperimentalAnnotation("kotlin.Experimental")
dependencies { dependencies {
......
package net.mamoe.mirai.utils
fun <K, V> Map<K, V>.firstValue(): V = this.entries.first().value
fun <K, V> Map<K, V>.firstValueOrNull(): V? = this.entries.firstOrNull()?.value
fun <K, V> Map<K, V>.firstKey(): K = this.entries.first().key
fun <K, V> Map<K, V>.firstKeyOrNull(): K? = this.entries.firstOrNull()?.key
\ No newline at end of file
...@@ -30,7 +30,7 @@ kotlin { ...@@ -30,7 +30,7 @@ kotlin {
sourceSets { sourceSets {
all { all {
languageSettings.enableLanguageFeature("InlineClasses") languageSettings.enableLanguageFeature("InlineClasses")
languageSettings.enableLanguageFeature("NewInference")
languageSettings.useExperimentalAnnotation("kotlin.Experimental") languageSettings.useExperimentalAnnotation("kotlin.Experimental")
} }
} }
......
...@@ -17,7 +17,7 @@ kotlin { ...@@ -17,7 +17,7 @@ kotlin {
sourceSets { sourceSets {
all { all {
languageSettings.enableLanguageFeature("InlineClasses") languageSettings.enableLanguageFeature("InlineClasses")
languageSettings.enableLanguageFeature("NewInference")
languageSettings.useExperimentalAnnotation("kotlin.Experimental") languageSettings.useExperimentalAnnotation("kotlin.Experimental")
} }
} }
......
...@@ -20,7 +20,7 @@ kotlin { ...@@ -20,7 +20,7 @@ kotlin {
sourceSets { sourceSets {
all { all {
languageSettings.enableLanguageFeature("InlineClasses") languageSettings.enableLanguageFeature("InlineClasses")
languageSettings.enableLanguageFeature("NewInference")
languageSettings.useExperimentalAnnotation("kotlin.Experimental") languageSettings.useExperimentalAnnotation("kotlin.Experimental")
} }
} }
......
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