1
0
mirror of https://github.com/mamoe/mirai.git synced 2025-04-09 02:10:10 +08:00

Simplify MessageChain implementations

This commit is contained in:
Him188 2020-12-11 14:53:47 +08:00
parent ffbc904bec
commit 6b792e3ba6
6 changed files with 62 additions and 94 deletions
mirai-core-api/src

View File

@ -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

View File

@ -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)
}
}

View File

@ -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] */

View File

@ -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))
//////////////////////

View File

@ -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 = "")
)
}
}

View File

@ -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])
}