From 6b792e3ba60ba3a4693e91d30c30f04da1f8673a Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Fri, 11 Dec 2020 14:53:47 +0800 Subject: [PATCH] Simplify MessageChain implementations --- .../kotlin/message/data/CombinedMessage.kt | 48 ++++++------ .../kotlin/message/data/MessageChain.kt | 6 +- .../message/data/MessageChainBuilder.kt | 2 +- .../commonMain/kotlin/message/data/impl.kt | 75 ++++++++----------- .../message.data/CombinedMessageTest.kt | 4 +- .../message.data/ConstrainSingleTest.kt | 21 +----- 6 files changed, 62 insertions(+), 94 deletions(-) diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/CombinedMessage.kt b/mirai-core-api/src/commonMain/kotlin/message/data/CombinedMessage.kt index a8c008a03..bc3069db8 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/CombinedMessage.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/CombinedMessage.kt @@ -12,31 +12,29 @@ package net.mamoe.mirai.message.data -import kotlinx.serialization.Serializable -import kotlin.LazyThreadSafetyMode.NONE - -/** - * 快速链接的两个消息 (避免构造新的 list). - * - * 不要直接构造 [CombinedMessage], 使用 [Message.plus] - * 要连接多个 [Message], 使用 [buildMessageChain] - * - * @see Message.plus - * - * Left-biased list - */ -@Serializable -internal data class CombinedMessage -internal constructor( - @JvmField internal val left: Message, // 必须已经完成 constrain single - @JvmField internal val tail: Message -) : Message, MessageChain, List<SingleMessage> by (left.flatten() + tail.flatten()).toList() { - private val toStringCache: String by lazy(NONE) { left.contentToString() + tail.contentToString() } - override fun toString(): String = toStringCache - - private val contentToStringCache: String by lazy(NONE) { left.contentToString() + tail.contentToString() } - override fun contentToString(): String = contentToStringCache -} +// +///** +// * 快速链接的两个消息 (避免构造新的 list). +// * +// * 不要直接构造 [CombinedMessage], 使用 [Message.plus] +// * 要连接多个 [Message], 使用 [buildMessageChain] +// * +// * @see Message.plus +// * +// * Left-biased list +// */ +//@Serializable +//internal data class CombinedMessage +//internal constructor( +// @JvmField internal val left: Message, // 必须已经完成 constrain single +// @JvmField internal val tail: Message +//) : Message, MessageChain, List<SingleMessage> by (left.flatten() + tail.flatten()).toList() { +// private val toStringCache: String by lazy(NONE) { left.contentToString() + tail.contentToString() } +// override fun toString(): String = toStringCache +// +// private val contentToStringCache: String by lazy(NONE) { left.contentToString() + tail.contentToString() } +// override fun contentToString(): String = contentToStringCache +//} /* @JvmSynthetic diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/MessageChain.kt b/mirai-core-api/src/commonMain/kotlin/message/data/MessageChain.kt index 753d5b44b..bdd9fff44 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/MessageChain.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/MessageChain.kt @@ -291,7 +291,6 @@ public inline fun messageChainOf(vararg messages: Message): MessageChain = messa @Suppress("UNCHECKED_CAST") public fun Message.asMessageChain(): MessageChain = when (this) { is MessageChain -> this - is CombinedMessage -> (this as Iterable<Message>).asMessageChain() else -> SingleMessageChainImpl(this as SingleMessage) } @@ -306,7 +305,7 @@ public fun SingleMessage.asMessageChain(): MessageChain = SingleMessageChainImpl */ @JvmSynthetic public fun Collection<SingleMessage>.asMessageChain(): MessageChain = - MessageChainImplByCollection(this.constrainSingleMessages()) + MessageChainImpl(this.constrainSingleMessages()) /** * 将 [this] [扁平化后][flatten] 委托为一个 [MessageChain] @@ -332,7 +331,7 @@ public fun Collection<Message>.asMessageChain(): MessageChain = MessageChainImpl */ @JvmSynthetic public fun Iterable<SingleMessage>.asMessageChain(): MessageChain = - MessageChainImplByCollection(this.constrainSingleMessages()) + MessageChainImpl(this.constrainSingleMessages()) @JvmSynthetic public inline fun MessageChain.asMessageChain(): MessageChain = this // 避免套娃 @@ -421,7 +420,6 @@ public inline fun Array<out SingleMessage>.flatten(): Sequence<SingleMessage> = public fun Message.flatten(): Sequence<SingleMessage> { return when (this) { is MessageChain -> this.asSequence() - is CombinedMessage -> this.asSequence() // already constrained single. else -> sequenceOf(this as SingleMessage) } } diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/MessageChainBuilder.kt b/mirai-core-api/src/commonMain/kotlin/message/data/MessageChainBuilder.kt index 01e19feed..8040c623f 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/MessageChainBuilder.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/MessageChainBuilder.kt @@ -148,7 +148,7 @@ public open class MessageChainBuilder private constructor( public fun asMessageChain(): MessageChain { built = true this.flushCache() - return MessageChainImplByCollection(this.constrainSingleMessages()) + return MessageChainImpl(this.constrainSingleMessages()) } /** 同 [asMessageChain] */ diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/impl.kt b/mirai-core-api/src/commonMain/kotlin/message/data/impl.kt index 492bef04a..4f035ad87 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/impl.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/impl.kt @@ -13,6 +13,7 @@ package net.mamoe.mirai.message.data +import kotlinx.serialization.Serializable import net.mamoe.mirai.message.data.Image.Key.FRIEND_IMAGE_ID_REGEX_1 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 @@ -25,15 +26,16 @@ import kotlin.native.concurrent.SharedImmutable //// IMPLEMENTATIONS //// ///////////////////////// +@Suppress("unused", "UNUSED_PARAMETER") private fun Message.hasDuplicationOfConstrain(key: MessageKey<*>): Boolean { - return when (this) { - is SingleMessage -> (this as? ConstrainSingle)?.key == key - is CombinedMessage -> return this.left.hasDuplicationOfConstrain(key) || this.tail.hasDuplicationOfConstrain(key) - is SingleMessageChainImpl -> (this.delegate as? ConstrainSingle)?.key == key - is MessageChainImplByCollection -> this.delegate.any { (it as? ConstrainSingle)?.key == key } - is MessageChainImplBySequence -> this.any { (it as? ConstrainSingle)?.key == key } - else -> error("stub") - } + return true + /* + return when (this) { + is SingleMessage -> (this as? ConstrainSingle)?.key == key + is CombinedMessage -> return this.left.hasDuplicationOfConstrain(key) || this.tail.hasDuplicationOfConstrain(key) + is MessageChainImplByCollection -> this.delegate.any { (it as? ConstrainSingle)?.key == key } + else -> error("stub") + }*/ } //@JvmSynthetic @@ -64,6 +66,8 @@ private fun Message.hasDuplicationOfConstrain(key: MessageKey<*>): Boolean { @JvmSynthetic internal fun Message.followedByImpl(tail: Message): MessageChain { + return MessageChainImplBySequence(this.flatten() + tail.flatten()) + /* when { this is SingleMessage && tail is SingleMessage -> { if (this is ConstrainSingle && tail is ConstrainSingle) { @@ -103,7 +107,7 @@ internal fun Message.followedByImpl(tail: Message): MessageChain { constrainSingleMessagesImpl(this.asSequence() + tail) ) } - } + }*/ } @@ -162,49 +166,36 @@ internal fun <M : SingleMessage> MessageChain.getImpl(key: MessageKey<M>): M? { /** * 使用 [Collection] 作为委托的 [MessageChain] */ -internal class MessageChainImplByCollection constructor( +@Serializable +internal data class MessageChainImpl constructor( + @JvmField internal val delegate: List<SingleMessage> // 必须 constrainSingleMessages, 且为 immutable ) : Message, MessageChain, List<SingleMessage> by delegate { override val size: Int get() = delegate.size override fun iterator(): Iterator<SingleMessage> = delegate.iterator() - private var toStringTemp: String? = null - get() = field ?: this.delegate.joinToString("") { it.toString() }.also { field = it } + private val toStringTemp: String by lazy { this.delegate.joinToString("") { it.toString() } } + override fun toString(): String = toStringTemp - override fun toString(): String = toStringTemp!! - - private var contentToStringTemp: String? = null - get() = field ?: this.delegate.joinToString("") { it.contentToString() }.also { field = it } - - override fun contentToString(): String = contentToStringTemp!! + private val contentToStringTemp: String by lazy { this.delegate.joinToString("") { it.contentToString() } } + override fun contentToString(): String = contentToStringTemp } -/** - * 使用 [Iterable] 作为委托的 [MessageChain] - */ -internal class MessageChainImplBySequence constructor( +@Suppress("FunctionName") +internal fun CombinedMessage( + left: Message, + tail: Message +): MessageChain = MessageChainImplBySequence(left.flatten() + tail.flatten()) + +@Suppress("FunctionName") // source compatibility with 1.x +internal fun MessageChainImplBySequence( delegate: Sequence<SingleMessage> // 可以有重复 ConstrainSingle -) : Message, Iterable<SingleMessage>, MessageChain, List<SingleMessage> by delegate.constrainSingleMessages() { - private var toStringTemp: String? = null - get() = field ?: this.joinToString("") { it.toString() }.also { field = it } +): MessageChain = MessageChainImpl(delegate.constrainSingleMessages()) - override fun toString(): String = toStringTemp!! - - private var contentToStringTemp: String? = null - get() = field ?: this.joinToString("") { it.contentToString() }.also { field = it } - - override fun contentToString(): String = contentToStringTemp!! -} - -/** - * 单个 [SingleMessage] 作为 [MessageChain] - */ -internal class SingleMessageChainImpl constructor( - internal val delegate: SingleMessage -) : Message, MessageChain, List<SingleMessage> by listOf(delegate) { - override fun toString(): String = this.delegate.toString() - override fun contentToString(): String = this.delegate.contentToString() -} +@Suppress("FunctionName") +internal fun SingleMessageChainImpl( + delegate: SingleMessage +): MessageChain = MessageChainImpl(listOf(delegate)) ////////////////////// diff --git a/mirai-core-api/src/commonTest/kotlin/message.data/CombinedMessageTest.kt b/mirai-core-api/src/commonTest/kotlin/message.data/CombinedMessageTest.kt index 41a1ff741..45438afe5 100644 --- a/mirai-core-api/src/commonTest/kotlin/message.data/CombinedMessageTest.kt +++ b/mirai-core-api/src/commonTest/kotlin/message.data/CombinedMessageTest.kt @@ -22,7 +22,7 @@ internal class CombinedMessageTest { assertEquals( "Hello World", - (message as CombinedMessage).asSequence().joinToString(separator = "") + message.flatten().joinToString(separator = "") ) } @@ -37,7 +37,7 @@ internal class CombinedMessageTest { assertEquals( "Hello World", - (message as CombinedMessage).asSequence().joinToString(separator = "") + message.flatten().joinToString(separator = "") ) } } diff --git a/mirai-core-api/src/commonTest/kotlin/message.data/ConstrainSingleTest.kt b/mirai-core-api/src/commonTest/kotlin/message.data/ConstrainSingleTest.kt index 06f3d6cde..c6822299b 100644 --- a/mirai-core-api/src/commonTest/kotlin/message.data/ConstrainSingleTest.kt +++ b/mirai-core-api/src/commonTest/kotlin/message.data/ConstrainSingleTest.kt @@ -30,16 +30,6 @@ internal class TestConstrainSingleMessage : ConstrainSingle, Any() { internal class ConstrainSingleTest { - @Test - fun testCombine() { - val result = PlainText("te") + PlainText("st") - assertTrue(result is CombinedMessage) - assertEquals("te", result.left.contentToString()) - assertEquals("st", result.tail.contentToString()) - assertEquals(2, result.size) - assertEquals("test", result.contentToString()) - } - @Test fun testSinglePlusChain() { val result = PlainText("te") + buildMessageChain { @@ -63,15 +53,6 @@ internal class ConstrainSingleTest { assertTrue { result.first() is TestConstrainSingleMessage } } - @Test - fun testSinglePlusSingle() { - val new = TestConstrainSingleMessage() - val combined = (TestConstrainSingleMessage() + new) - - assertTrue(combined is SingleMessageChainImpl) - assertSame(new, combined.delegate) - } - @Test fun testChainPlusSingle() { val new = TestConstrainSingleMessage() @@ -92,7 +73,7 @@ internal class ConstrainSingleTest { assertEquals(7, result.size) assertEquals(" [OK]ss p test", result.contentToString()) - result as MessageChainImplByCollection + result as MessageChainImpl assertSame(new, result.delegate.toTypedArray()[2]) }