Fix serialization

This commit is contained in:
Him188 2020-12-26 23:42:44 +08:00
parent 5196cc410a
commit eacdfed97a
9 changed files with 268 additions and 61 deletions

View File

@ -12,6 +12,7 @@ package net.mamoe.mirai.message
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.modules.PolymorphicModuleBuilder import kotlinx.serialization.modules.PolymorphicModuleBuilder
@ -21,6 +22,7 @@ import kotlinx.serialization.modules.polymorphic
import net.mamoe.mirai.Mirai import net.mamoe.mirai.Mirai
import net.mamoe.mirai.message.data.* import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.utils.MiraiExperimentalApi import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.MiraiInternalApi
import kotlin.reflect.KClass import kotlin.reflect.KClass
@MiraiExperimentalApi @MiraiExperimentalApi
@ -34,9 +36,12 @@ public interface MessageSerializer {
public fun clearRegisteredSerializers() public fun clearRegisteredSerializers()
} }
internal object MessageSourceSerializer : KSerializer<MessageSource> { @MiraiInternalApi
public open class MessageSourceSerializerImpl(serialName: String) : KSerializer<MessageSource> {
public companion object : MessageSourceSerializerImpl("net.mamoe.mirai.message.data.MessageSource")
@Serializable @Serializable
class SerialData( internal class SerialData(
val kind: MessageSourceKind, val kind: MessageSourceKind,
val bot: Long, val bot: Long,
val ids: IntArray, val ids: IntArray,
@ -47,7 +52,17 @@ internal object MessageSourceSerializer : KSerializer<MessageSource> {
val originalMessage: MessageChain, val originalMessage: MessageChain,
) )
override val descriptor: SerialDescriptor = SerialData.serializer().descriptor override val descriptor: SerialDescriptor = buildClassSerialDescriptor(serialName) {
val desc = SerialData.serializer().descriptor
repeat(SerialData.serializer().descriptor.elementsCount) { index ->
element(
desc.getElementName(index),
desc.getElementDescriptor(index),
desc.getElementAnnotations(index),
desc.isElementOptional(index)
)
}
}
// buildClassSerialDescriptor("MessageSource") { // buildClassSerialDescriptor("MessageSource") {
// element("bot", Long.serializer().descriptor) // element("bot", Long.serializer().descriptor)
// element("ids", ArraySerializer(Int.serializer()).descriptor) // element("ids", ArraySerializer(Int.serializer()).descriptor)
@ -96,7 +111,6 @@ private val builtInSerializersModule by lazy {
contextual(CustomMessage::class, CustomMessage.serializer()) contextual(CustomMessage::class, CustomMessage.serializer())
contextual(CustomMessageMetadata::class, CustomMessageMetadata.serializer()) contextual(CustomMessageMetadata::class, CustomMessageMetadata.serializer())
contextual(Face::class, Face.serializer()) contextual(Face::class, Face.serializer())
contextual(MessageSource::class, MessageSource.serializer())
contextual(Image::class, Image.Serializer) contextual(Image::class, Image.Serializer)
contextual(PlainText::class, PlainText.serializer()) contextual(PlainText::class, PlainText.serializer())
contextual(QuoteReply::class, QuoteReply.serializer()) contextual(QuoteReply::class, QuoteReply.serializer())
@ -117,8 +131,12 @@ private val builtInSerializersModule by lazy {
contextual(FlashImage::class, FlashImage.serializer()) contextual(FlashImage::class, FlashImage.serializer())
fun PolymorphicModuleBuilder<SingleMessage>.singleMessageSubclasses() { fun PolymorphicModuleBuilder<SingleMessage>.singleMessageSubclasses() {
// subclass(MessageSource::class, MessageSource.serializer())
} }
// contextual(MessageSource::class, MessageSource.serializer())
polymorphicDefault(MessageSource::class) { MessageSource.serializer() }
fun PolymorphicModuleBuilder<MessageMetadata>.messageMetadataSubclasses() { fun PolymorphicModuleBuilder<MessageMetadata>.messageMetadataSubclasses() {
subclass(MessageSource::class, MessageSource.serializer()) subclass(MessageSource::class, MessageSource.serializer())
subclass(QuoteReply::class, QuoteReply.serializer()) subclass(QuoteReply::class, QuoteReply.serializer())
@ -148,7 +166,14 @@ private val builtInSerializersModule by lazy {
subclass(FlashImage::class, FlashImage.serializer()) subclass(FlashImage::class, FlashImage.serializer())
} }
contextual(Message::class, Message.Serializer)
// contextual(SingleMessage::class, SingleMessage.Serializer)
contextual(MessageChain::class, MessageChain.Serializer) contextual(MessageChain::class, MessageChain.Serializer)
contextual(MessageChainImpl::class, MessageChainImpl.serializer())
polymorphic(MessageChain::class) {
subclass(MessageChainImpl::class, MessageChainImpl.serializer())
}
polymorphicDefault(MessageChain::class) { MessageChainImpl.serializer() } polymorphicDefault(MessageChain::class) { MessageChainImpl.serializer() }
polymorphic(AbstractServiceMessage::class) { polymorphic(AbstractServiceMessage::class) {
@ -156,9 +181,15 @@ private val builtInSerializersModule by lazy {
subclass(ForwardMessageInternal::class, ForwardMessageInternal.serializer()) subclass(ForwardMessageInternal::class, ForwardMessageInternal.serializer())
} }
// polymorphic(SingleMessage::class) {
// subclass(MessageSource::class, MessageSource.serializer())
// default {
// Message.Serializer.serializersModule.getPolymorphic(Message::class, it)
// }
// }
polymorphicDefault(Image::class) { Image.Serializer } polymorphicDefault(Image::class) { Image.Serializer }
contextual(Message::class, Message.Serializer)
// polymorphic(Message::class) { // polymorphic(Message::class) {
// subclass(PlainText::class, PlainText.serializer()) // subclass(PlainText::class, PlainText.serializer())
// } // }
@ -166,6 +197,7 @@ private val builtInSerializersModule by lazy {
messageContentSubclasses() messageContentSubclasses()
messageMetadataSubclasses() messageMetadataSubclasses()
singleMessageSubclasses() singleMessageSubclasses()
subclass(MessageChainImpl::class, MessageChainImpl.serializer())
} }
//contextual(SingleMessage::class, SingleMessage.Serializer) //contextual(SingleMessage::class, SingleMessage.Serializer)

View File

@ -209,8 +209,12 @@ public interface Message { // must be interface. Don't consider any changes.
*/ */
@JvmOverloads @JvmOverloads
@JvmStatic @JvmStatic
public fun deserializeFromJsonString(string: String, json: Json = Json.Default): Message = public fun deserializeFromJsonString(
json.decodeFromString(Serializer, string) string: String,
json: Json = Json { serializersModule = Serializer.serializersModule }
): Message {
return json.decodeFromString(Serializer, string)
}
/** /**
* [Message] 序列化为 JSON 字符串. * [Message] 序列化为 JSON 字符串.
@ -218,8 +222,9 @@ public interface Message { // must be interface. Don't consider any changes.
*/ */
@JvmOverloads @JvmOverloads
@JvmStatic @JvmStatic
public fun Message.serializeToJsonString(json: Json = Json.Default): String = public fun Message.serializeToJsonString(
json.encodeToString(Serializer, this) json: Json = Json { serializersModule = Serializer.serializersModule }
): String = json.encodeToString(Serializer, this)
/** /**
* [Message] 序列化为指定格式的字符串. * [Message] 序列化为指定格式的字符串.
@ -320,9 +325,10 @@ public inline operator fun Message.times(count: Int): MessageChain = this.repeat
/** /**
* 单个消息元素. 与之相对的是 [MessageChain], 是多个 [SingleMessage] 的集合. * 单个消息元素. 与之相对的是 [MessageChain], 是多个 [SingleMessage] 的集合.
*/ */
@Serializable(SingleMessage.Serializer::class) // @Serializable(SingleMessage.Serializer::class)
public interface SingleMessage : Message { public interface SingleMessage : Message {
public object Serializer : KSerializer<SingleMessage> by PolymorphicSerializer(SingleMessage::class) // @kotlinx.serialization.Serializer(forClass = SingleMessage::class)
// public object Serializer : KSerializer<SingleMessage> by PolymorphicSerializer(SingleMessage::class)
} }
/** /**

View File

@ -13,12 +13,12 @@
package net.mamoe.mirai.message.data package net.mamoe.mirai.message.data
import kotlinx.serialization.KSerializer import kotlinx.serialization.*
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.ListSerializer import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json
import net.mamoe.mirai.event.events.MessageEvent import net.mamoe.mirai.event.events.MessageEvent
import net.mamoe.mirai.message.code.CodableMessage import net.mamoe.mirai.message.code.CodableMessage
import net.mamoe.mirai.message.data.MessageSource.Key.quote import net.mamoe.mirai.message.data.MessageSource.Key.quote
@ -104,6 +104,42 @@ public interface MessageChain : Message, List<SingleMessage>, RandomAccess, Coda
override fun appendMiraiCode(builder: StringBuilder) { override fun appendMiraiCode(builder: StringBuilder) {
forEach { it.safeCast<CodableMessage>()?.appendMiraiCode(builder) } forEach { it.safeCast<CodableMessage>()?.appendMiraiCode(builder) }
} }
public companion object {
/**
* JSON 字符串解析 [MessageChain]
* @see serializeToJsonString
*/
@JvmOverloads
@JvmStatic
public fun deserializeFromJsonString(
string: String,
json: Json = Json { serializersModule = Message.Serializer.serializersModule }
): MessageChain {
return json.decodeFromString(Serializer, string)
}
/**
* [MessageChain] 序列化为 JSON 字符串.
* @see deserializeFromJsonString
*/
@JvmOverloads
@JvmStatic
public fun MessageChain.serializeToJsonString(
json: Json = Json { serializersModule = Message.Serializer.serializersModule }
): String = json.encodeToString(Message.Serializer, this)
/**
* [MessageChain] 序列化为指定格式的字符串.
*
* @see serializeToJsonString
* @see StringFormat.encodeToString
*/
@ExperimentalSerializationApi
@JvmStatic
public fun MessageChain.serializeToString(format: StringFormat): String =
format.encodeToString(Serializer, this)
}
} }
// region accessors // region accessors

View File

@ -25,7 +25,7 @@ import net.mamoe.mirai.contact.*
import net.mamoe.mirai.event.events.MessageEvent import net.mamoe.mirai.event.events.MessageEvent
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.MessageReceipt.Companion.recall import net.mamoe.mirai.message.MessageReceipt.Companion.recall
import net.mamoe.mirai.message.MessageSourceSerializer import net.mamoe.mirai.message.MessageSourceSerializerImpl
import net.mamoe.mirai.message.data.MessageSource.Key.isAboutFriend import net.mamoe.mirai.message.data.MessageSource.Key.isAboutFriend
import net.mamoe.mirai.message.data.MessageSource.Key.isAboutGroup import net.mamoe.mirai.message.data.MessageSource.Key.isAboutGroup
import net.mamoe.mirai.message.data.MessageSource.Key.isAboutTemp import net.mamoe.mirai.message.data.MessageSource.Key.isAboutTemp
@ -69,7 +69,7 @@ import net.mamoe.mirai.utils.safeCast
* *
* @see buildMessageSource 构造一个 [OfflineMessageSource] * @see buildMessageSource 构造一个 [OfflineMessageSource]
*/ */
@Serializable(MessageSourceSerializer::class) @Serializable(MessageSourceSerializerImpl.Companion::class)
public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle { public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle {
@ExperimentalMessageKey @ExperimentalMessageKey
public final override val key: MessageKey<MessageSource> public final override val key: MessageKey<MessageSource>

View File

@ -25,7 +25,6 @@ import net.mamoe.mirai.internal.contact.*
import net.mamoe.mirai.internal.message.* import net.mamoe.mirai.internal.message.*
import net.mamoe.mirai.internal.network.highway.HighwayHelper import net.mamoe.mirai.internal.network.highway.HighwayHelper
import net.mamoe.mirai.internal.network.protocol.data.jce.SvcDevLoginInfo import net.mamoe.mirai.internal.network.protocol.data.jce.SvcDevLoginInfo
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.internal.network.protocol.data.proto.LongMsg import net.mamoe.mirai.internal.network.protocol.data.proto.LongMsg
import net.mamoe.mirai.internal.network.protocol.packet.chat.* import net.mamoe.mirai.internal.network.protocol.packet.chat.*
import net.mamoe.mirai.internal.network.protocol.packet.chat.voice.PttStore import net.mamoe.mirai.internal.network.protocol.packet.chat.voice.PttStore
@ -40,7 +39,6 @@ import net.mamoe.mirai.message.data.Image.Key.FRIEND_IMAGE_ID_REGEX_2
import net.mamoe.mirai.message.data.Image.Key.GROUP_IMAGE_ID_REGEX import net.mamoe.mirai.message.data.Image.Key.GROUP_IMAGE_ID_REGEX
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
import kotlin.random.Random import kotlin.random.Random
@ -54,6 +52,15 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
Message.Serializer.registerSerializer(OfflineGroupImage::class, OfflineGroupImage.serializer()) Message.Serializer.registerSerializer(OfflineGroupImage::class, OfflineGroupImage.serializer())
Message.Serializer.registerSerializer(OfflineFriendImage::class, OfflineFriendImage.serializer()) Message.Serializer.registerSerializer(OfflineFriendImage::class, OfflineFriendImage.serializer())
Message.Serializer.registerSerializer(MarketFaceImpl::class, MarketFaceImpl.serializer()) Message.Serializer.registerSerializer(MarketFaceImpl::class, MarketFaceImpl.serializer())
Message.Serializer.registerSerializer(
OfflineMessageSourceImplData::class,
OfflineMessageSourceImplData.serializer()
)
Message.Serializer.registerSerializer(
MessageSourceFromGroupImpl::class,
MessageSourceFromGroupImpl.serializer()
)
} }
} }
@ -843,38 +850,8 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
time: Int, time: Int,
internalIds: IntArray, internalIds: IntArray,
originalMessage: MessageChain originalMessage: MessageChain
): OfflineMessageSource { ): OfflineMessageSource = OfflineMessageSourceImplData(
return object : OfflineMessageSource(), MessageSourceInternal { kind, ids, botId, time, fromUin, targetUin, originalMessage, internalIds
override val kind: MessageSourceKind get() = kind
override val ids: IntArray get() = ids
override val botId: Long get() = botId
override val time: Int get() = time
override val fromId: Long get() = fromUin
override val targetId: Long get() = targetUin
override val originalMessage: MessageChain get() = originalMessage
override val sequenceIds: IntArray = ids
override val internalIds: IntArray = internalIds
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
override fun toJceData(): ImMsgBody.SourceMsg {
return ImMsgBody.SourceMsg(
origSeqs = sequenceIds,
senderUin = fromUin,
toUin = 0,
flag = 1,
elems = originalMessage.toRichTextElems(
null, //forGroup = kind == MessageSourceKind.GROUP,
withGeneralFlags = false
),
type = 0,
time = time,
pbReserve = EMPTY_BYTE_ARRAY,
srcMsg = EMPTY_BYTE_ARRAY
) )
}
}
}
} }

View File

@ -11,6 +11,8 @@
package net.mamoe.mirai.internal.message package net.mamoe.mirai.internal.message
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.Friend import net.mamoe.mirai.contact.Friend
import net.mamoe.mirai.contact.Member import net.mamoe.mirai.contact.Member
@ -22,6 +24,7 @@ import net.mamoe.mirai.internal.network.protocol.data.proto.SourceMsg
import net.mamoe.mirai.internal.network.protocol.packet.EMPTY_BYTE_ARRAY import net.mamoe.mirai.internal.network.protocol.packet.EMPTY_BYTE_ARRAY
import net.mamoe.mirai.internal.utils._miraiContentToString import net.mamoe.mirai.internal.utils._miraiContentToString
import net.mamoe.mirai.internal.utils.io.serialization.toByteArray import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
import net.mamoe.mirai.message.MessageSourceSerializerImpl
import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.MessageSource import net.mamoe.mirai.message.data.MessageSource
@ -32,12 +35,17 @@ import net.mamoe.mirai.utils.mapToIntArray
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
internal interface MessageSourceInternal { internal interface MessageSourceInternal {
@Transient
val sequenceIds: IntArray val sequenceIds: IntArray
@Transient
val internalIds: IntArray // randomId val internalIds: IntArray // randomId
@Deprecated("don't use this internally. Use sequenceId or random instead.", level = DeprecationLevel.ERROR) @Deprecated("don't use this internally. Use sequenceId or random instead.", level = DeprecationLevel.ERROR)
@Transient
val ids: IntArray val ids: IntArray
@Transient
val isRecalledOrPlanned: AtomicBoolean val isRecalledOrPlanned: AtomicBoolean
fun toJceData(): ImMsgBody.SourceMsg fun toJceData(): ImMsgBody.SourceMsg
@ -148,10 +156,14 @@ internal class MessageSourceFromTempImpl(
override fun toJceData(): ImMsgBody.SourceMsg = jceData override fun toJceData(): ImMsgBody.SourceMsg = jceData
} }
@Serializable(MessageSourceFromGroupImpl.Serializer::class)
internal data class MessageSourceFromGroupImpl( internal data class MessageSourceFromGroupImpl(
override val bot: Bot, override val bot: Bot,
private val msg: List<MsgComm.Msg> private val msg: List<MsgComm.Msg>
) : OnlineMessageSource.Incoming.FromGroup(), MessageSourceInternal { ) : OnlineMessageSource.Incoming.FromGroup(), MessageSourceInternal {
object Serializer : MessageSourceSerializerImpl("net.mamoe.mirai.internal.message.MessageSourceFromGroupImpl")
@Transient
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false) override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
override val sequenceIds: IntArray get() = msg.mapToIntArray { it.msgHead.msgSeq } override val sequenceIds: IntArray get() = msg.mapToIntArray { it.msgHead.msgSeq }
override val internalIds: IntArray get() = msg.mapToIntArray { it.msgBody.richText.attr!!.random } override val internalIds: IntArray get() = msg.mapToIntArray { it.msgBody.richText.attr!!.random }

View File

@ -11,6 +11,8 @@
package net.mamoe.mirai.internal.message package net.mamoe.mirai.internal.message
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
import net.mamoe.mirai.internal.network.protocol.data.proto.SourceMsg import net.mamoe.mirai.internal.network.protocol.data.proto.SourceMsg
@ -22,6 +24,70 @@ import net.mamoe.mirai.message.data.OfflineMessageSource
import net.mamoe.mirai.utils.mapToIntArray import net.mamoe.mirai.utils.mapToIntArray
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
@Serializable
internal data class OfflineMessageSourceImplData(
override val kind: MessageSourceKind,
override val ids: IntArray,
override val botId: Long,
override val time: Int,
override val fromId: Long,
override val targetId: Long,
override val originalMessage: MessageChain,
override val internalIds: IntArray,
) : OfflineMessageSource(), MessageSourceInternal {
override val sequenceIds: IntArray get() = ids
@Transient
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
override fun toJceData(): ImMsgBody.SourceMsg {
return ImMsgBody.SourceMsg(
origSeqs = sequenceIds,
senderUin = fromId,
toUin = 0,
flag = 1,
elems = originalMessage.toRichTextElems(
null, //forGroup = kind == MessageSourceKind.GROUP,
withGeneralFlags = false
),
type = 0,
time = time,
pbReserve = net.mamoe.mirai.internal.EMPTY_BYTE_ARRAY,
srcMsg = net.mamoe.mirai.internal.EMPTY_BYTE_ARRAY
)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as OfflineMessageSourceImplData
if (kind != other.kind) return false
if (!ids.contentEquals(other.ids)) return false
if (botId != other.botId) return false
if (time != other.time) return false
if (fromId != other.fromId) return false
if (targetId != other.targetId) return false
if (originalMessage != other.originalMessage) return false
if (!internalIds.contentEquals(other.internalIds)) return false
return true
}
override fun hashCode(): Int {
var result = kind.hashCode()
result = 31 * result + ids.contentHashCode()
result = 31 * result + botId.hashCode()
result = 31 * result + time
result = 31 * result + fromId.hashCode()
result = 31 * result + targetId.hashCode()
result = 31 * result + originalMessage.hashCode()
result = 31 * result + internalIds.contentHashCode()
return result
}
}
internal class OfflineMessageSourceImplByMsg( internal class OfflineMessageSourceImplByMsg(
// from other sources' originalMessage // from other sources' originalMessage

View File

@ -563,7 +563,7 @@ internal class ImMsgBody : ProtoBuf {
) : ProtoBuf ) : ProtoBuf
@Serializable @Serializable
internal class MarketFace( internal data class MarketFace(
@ProtoNumber(1) @JvmField val faceName: ByteArray = EMPTY_BYTE_ARRAY, @ProtoNumber(1) @JvmField val faceName: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoNumber(2) @JvmField val itemType: Int = 0, @ProtoNumber(2) @JvmField val itemType: Int = 0,
@ProtoNumber(3) @JvmField val faceInfo: Int = 0, @ProtoNumber(3) @JvmField val faceInfo: Int = 0,
@ -577,7 +577,48 @@ internal class ImMsgBody : ProtoBuf {
@ProtoNumber(11) @JvmField val imageHeight: Int = 0, @ProtoNumber(11) @JvmField val imageHeight: Int = 0,
@ProtoNumber(12) @JvmField val mobileParam: ByteArray = EMPTY_BYTE_ARRAY, @ProtoNumber(12) @JvmField val mobileParam: ByteArray = EMPTY_BYTE_ARRAY,
@ProtoNumber(13) @JvmField val pbReserve: ByteArray = EMPTY_BYTE_ARRAY @ProtoNumber(13) @JvmField val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf ) : ProtoBuf {
@Suppress("DuplicatedCode")
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as MarketFace
if (!faceName.contentEquals(other.faceName)) return false
if (itemType != other.itemType) return false
if (faceInfo != other.faceInfo) return false
if (!faceId.contentEquals(other.faceId)) return false
if (tabId != other.tabId) return false
if (subType != other.subType) return false
if (!key.contentEquals(other.key)) return false
if (!param.contentEquals(other.param)) return false
if (mediaType != other.mediaType) return false
if (imageWidth != other.imageWidth) return false
if (imageHeight != other.imageHeight) return false
if (!mobileParam.contentEquals(other.mobileParam)) return false
if (!pbReserve.contentEquals(other.pbReserve)) return false
return true
}
override fun hashCode(): Int {
var result = faceName.contentHashCode()
result = 31 * result + itemType
result = 31 * result + faceInfo
result = 31 * result + faceId.contentHashCode()
result = 31 * result + tabId
result = 31 * result + subType
result = 31 * result + key.contentHashCode()
result = 31 * result + param.contentHashCode()
result = 31 * result + mediaType
result = 31 * result + imageWidth
result = 31 * result + imageHeight
result = 31 * result + mobileParam.contentHashCode()
result = 31 * result + pbReserve.contentHashCode()
return result
}
}
@Serializable @Serializable
internal class MarketTrans( internal class MarketTrans(

View File

@ -13,16 +13,19 @@ import kotlinx.serialization.KSerializer
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.serializer import kotlinx.serialization.serializer
import net.mamoe.mirai.Mirai import net.mamoe.mirai.Mirai
import net.mamoe.mirai.internal.message.MarketFaceImpl
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.message.data.* import net.mamoe.mirai.message.data.*
import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
internal class MessageSerializationTest { internal class MessageSerializationTest {
private val module = Message.Serializer.serializersModule private val module get() = Message.Serializer.serializersModule
private val format = Json { private val format
get() = Json {
serializersModule = module serializersModule = module
useArrayPolymorphism = false useArrayPolymorphism = false // ?
} }
private inline fun <reified T : Any> T.serialize(serializer: KSerializer<T> = module.serializer()): String { private inline fun <reified T : Any> T.serialize(serializer: KSerializer<T> = module.serializer()): String {
@ -34,23 +37,57 @@ internal class MessageSerializationTest {
} }
private inline fun <reified T : Any> testSerialization(t: T, serializer: KSerializer<T> = module.serializer()) { private inline fun <reified T : Any> testSerialization(t: T, serializer: KSerializer<T> = module.serializer()) {
val deserialized = t.serialize(serializer).deserialize(serializer)
assertEquals( assertEquals(
t, t,
t.serialize(serializer).deserialize(serializer), deserialized,
message = "serialized string: ${t.serialize(serializer)}" message = "serialized string: ${t.serialize(serializer)}\ndeserialized string: ${
deserialized.serialize(
serializer
)
}\n"
) )
} }
private val image = Image("{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.mirai")
private val testMessageContentInstances: Array<out MessageContent> = arrayOf( private val testMessageContentInstances: Array<out MessageContent> = arrayOf(
PlainText("test"), PlainText("test"),
At(123456), At(123456),
AtAll, AtAll,
Image("{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.mirai"), image,
image.toForwardMessage(1L, "test"),
VipFace(VipFace.AiXin, 1),
PokeMessage.BaoBeiQiu,
Face(Face.AI_NI),
MarketFaceImpl(ImMsgBody.MarketFace()),
image.flash(),
)
private val emptySource = Mirai.constructMessageSource(
1L,
MessageSourceKind.FRIEND,
1,
2,
intArrayOf(1),
1,
intArrayOf(1),
messageChainOf()
) )
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
private val testConstrainSingleMessageInstances: Array<out ConstrainSingle> = arrayOf( private val testConstrainSingleMessageInstances: Array<out ConstrainSingle> = arrayOf(
LongMessage("content", "resId") LongMessage("content", "resId"),
Mirai.constructMessageSource(
1L,
MessageSourceKind.FRIEND,
1,
2,
intArrayOf(1),
1,
intArrayOf(1),
messageChainOf(emptySource, image)
),
) )
companion object { companion object {