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:
parent
ffbc904bec
commit
6b792e3ba6
mirai-core-api/src
commonMain/kotlin/message/data
commonTest/kotlin/message.data
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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] */
|
||||
|
@ -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))
|
||||
|
||||
|
||||
//////////////////////
|
||||
|
@ -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 = "")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -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])
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user