Browse Source

Rearrange implementations

Him188 5 years ago
parent
commit
075ed6680f

+ 1 - 90
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt

@@ -285,93 +285,4 @@ interface MessageContent : SingleMessage
 @JvmSynthetic
 @Suppress("UNCHECKED_CAST")
 suspend inline fun <C : Contact> MessageChain.sendTo(contact: C): MessageReceipt<C> =
-    contact.sendMessage(this) as MessageReceipt<C>
-
-
-/////////////////////
-/// IMPLEMENTATIONS
-//////////////////////
-
-
-@OptIn(MiraiInternalAPI::class)
-private fun Message.hasDuplicationOfConstrain(key: Message.Key<*>): 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")
-    }
-}
-
-@OptIn(MiraiInternalAPI::class)
-@JvmSynthetic
-@Suppress("DEPRECATION_ERROR")
-internal fun Message.followedByInternalForBinaryCompatibility(tail: Message): CombinedMessage {
-    return CombinedMessage(EmptyMessageChain, this.followedBy(tail))
-}
-
-private fun Message.followedByImpl(tail: Message): MessageChain {
-    when {
-        this is SingleMessage && tail is SingleMessage -> {
-            if (this is ConstrainSingle<*> && tail is ConstrainSingle<*>) {
-                if (this.key == tail.key)
-                    return SingleMessageChainImpl(tail)
-            }
-            return CombinedMessage(this, tail)
-        }
-
-        this is SingleMessage -> { // tail is not
-            tail as MessageChain
-
-            if (this is ConstrainSingle<*>) {
-                val key = this.key
-                if (tail.any { (it as? ConstrainSingle<*>)?.key == key }) {
-                    return tail
-                }
-            }
-            return CombinedMessage(this, tail)
-        }
-
-        tail is SingleMessage -> {
-            this as MessageChain
-
-            if (tail is ConstrainSingle<*> && this.hasDuplicationOfConstrain(tail.key)) {
-                val iterator = this.iterator()
-                var tailUsed = false
-                return MessageChainImplByCollection(
-                    constrainSingleMessagesImpl {
-                        if (iterator.hasNext()) {
-                            iterator.next()
-                        } else if (!tailUsed) {
-                            tailUsed = true
-                            tail
-                        } else null
-                    }
-                )
-            }
-
-            return CombinedMessage(this, tail)
-        }
-
-        else -> { // both chain
-            this as MessageChain
-            tail as MessageChain
-
-            var iterator = this.iterator()
-            var tailUsed = false
-            return MessageChainImplByCollection(
-                constrainSingleMessagesImpl {
-                    if (iterator.hasNext()) {
-                        iterator.next()
-                    } else if (!tailUsed) {
-                        tailUsed = true
-                        iterator = tail.iterator()
-                        iterator.next()
-                    } else null
-                }
-            )
-        }
-    }
-}
+    contact.sendMessage(this) as MessageReceipt<C>

+ 5 - 164
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt

@@ -246,7 +246,7 @@ fun Collection<SingleMessage>.asMessageChain(): MessageChain =
  */
 @JvmName("newChain")
 // @JsName("newChain")
-inline fun Collection<Message>.asMessageChain(): MessageChain = MessageChainImplBySequence(this.flatten())
+fun Collection<Message>.asMessageChain(): MessageChain = MessageChainImplBySequence(this.flatten())
 
 /**
  * 直接将 [this] 委托为一个 [MessageChain]
@@ -256,27 +256,27 @@ fun Iterable<SingleMessage>.asMessageChain(): MessageChain =
     MessageChainImplByCollection(this.constrainSingleMessages())
 
 @JvmSynthetic
-inline fun MessageChain.asMessageChain(): MessageChain = this // 避免套娃
+fun MessageChain.asMessageChain(): MessageChain = this // 避免套娃
 
 /**
  * 将 [this] [扁平化后][flatten] 委托为一个 [MessageChain]
  */
 @JvmName("newChain")
 // @JsName("newChain")
-inline fun Iterable<Message>.asMessageChain(): MessageChain = MessageChainImplBySequence(this.flatten())
+fun Iterable<Message>.asMessageChain(): MessageChain = MessageChainImplBySequence(this.flatten())
 
 /**
  * 直接将 [this] 委托为一个 [MessageChain]
  */
 @JvmSynthetic
-inline fun Sequence<SingleMessage>.asMessageChain(): MessageChain = MessageChainImplBySequence(this)
+fun Sequence<SingleMessage>.asMessageChain(): MessageChain = MessageChainImplBySequence(this)
 
 /**
  * 将 [this] [扁平化后][flatten] 委托为一个 [MessageChain]
  */
 @JvmName("newChain")
 // @JsName("newChain")
-inline fun Sequence<Message>.asMessageChain(): MessageChain = MessageChainImplBySequence(this.flatten())
+fun Sequence<Message>.asMessageChain(): MessageChain = MessageChainImplBySequence(this.flatten())
 
 /**
  * 构造一个 [MessageChain]
@@ -386,162 +386,3 @@ object NullMessageChain : MessageChain {
     override fun equals(other: Any?): Boolean = other === this
     override fun iterator(): MutableIterator<SingleMessage> = error("accessing NullMessageChain")
 }
-
-
-////////////////////////////
-// region implementations
-///////////////////////////
-
-@OptIn(MiraiExperimentalAPI::class)
-internal fun Sequence<SingleMessage>.constrainSingleMessages(): List<SingleMessage> {
-    val iterator = this.iterator()
-    return constrainSingleMessagesImpl supplier@{
-        if (iterator.hasNext()) {
-            iterator.next()
-        } else null
-    }
-}
-
-@MiraiExperimentalAPI
-internal inline fun constrainSingleMessagesImpl(iterator: () -> SingleMessage?): ArrayList<SingleMessage> {
-    val list = ArrayList<SingleMessage>()
-    var firstConstrainIndex = -1
-
-    var next: SingleMessage?
-    do {
-        next = iterator()
-        next?.let { singleMessage ->
-            if (singleMessage is ConstrainSingle<*>) {
-                if (firstConstrainIndex == -1) {
-                    firstConstrainIndex = list.size // we are going to add one
-                } else {
-                    val key = singleMessage.key
-                    val index = list.indexOfFirst(firstConstrainIndex) { it is ConstrainSingle<*> && it.key == key }
-                    if (index != -1) {
-                        list[index] = singleMessage
-                        return@let
-                    }
-                }
-            }
-
-            list.add(singleMessage)
-        } ?: return list
-    } while (true)
-}
-
-@OptIn(MiraiExperimentalAPI::class)
-internal fun Iterable<SingleMessage>.constrainSingleMessages(): List<SingleMessage> {
-    val iterator = this.iterator()
-    return constrainSingleMessagesImpl supplier@{
-        if (iterator.hasNext()) {
-            iterator.next()
-        } else null
-    }
-}
-
-internal inline fun <T> List<T>.indexOfFirst(offset: Int, predicate: (T) -> Boolean): Int {
-    for (index in offset..this.lastIndex) {
-        if (predicate(this[index]))
-            return index
-    }
-    return -1
-}
-
-
-@OptIn(MiraiExperimentalAPI::class)
-@JvmSynthetic
-@Suppress("UNCHECKED_CAST")
-internal fun <M : Message> MessageChain.firstOrNullImpl(key: Message.Key<M>): M? = when (key) {
-    At -> firstIsInstanceOrNull<At>()
-    AtAll -> firstIsInstanceOrNull<AtAll>()
-    PlainText -> firstIsInstanceOrNull<PlainText>()
-    Image -> firstIsInstanceOrNull<Image>()
-    OnlineImage -> firstIsInstanceOrNull<OnlineImage>()
-    OfflineImage -> firstIsInstanceOrNull<OfflineImage>()
-    GroupImage -> firstIsInstanceOrNull<GroupImage>()
-    FriendImage -> firstIsInstanceOrNull<FriendImage>()
-    Face -> firstIsInstanceOrNull<Face>()
-    QuoteReply -> firstIsInstanceOrNull<QuoteReply>()
-    MessageSource -> firstIsInstanceOrNull<MessageSource>()
-    OnlineMessageSource -> firstIsInstanceOrNull<OnlineMessageSource>()
-    OfflineMessageSource -> firstIsInstanceOrNull<OfflineMessageSource>()
-    OnlineMessageSource.Outgoing -> firstIsInstanceOrNull<OnlineMessageSource.Outgoing>()
-    OnlineMessageSource.Outgoing.ToGroup -> firstIsInstanceOrNull<OnlineMessageSource.Outgoing.ToGroup>()
-    OnlineMessageSource.Outgoing.ToFriend -> firstIsInstanceOrNull<OnlineMessageSource.Outgoing.ToFriend>()
-    OnlineMessageSource.Incoming -> firstIsInstanceOrNull<OnlineMessageSource.Incoming>()
-    OnlineMessageSource.Incoming.FromGroup -> firstIsInstanceOrNull<OnlineMessageSource.Incoming.FromGroup>()
-    OnlineMessageSource.Incoming.FromFriend -> firstIsInstanceOrNull<OnlineMessageSource.Incoming.FromFriend>()
-    OnlineMessageSource -> firstIsInstanceOrNull<OnlineMessageSource>()
-    XmlMessage -> firstIsInstanceOrNull<XmlMessage>()
-    JsonMessage -> firstIsInstanceOrNull<JsonMessage>()
-    RichMessage -> firstIsInstanceOrNull<RichMessage>()
-    LightApp -> firstIsInstanceOrNull<LightApp>()
-    PokeMessage -> firstIsInstanceOrNull<PokeMessage>()
-    HummerMessage -> firstIsInstanceOrNull<HummerMessage>()
-    FlashImage -> firstIsInstanceOrNull<FlashImage>()
-    GroupFlashImage -> firstIsInstanceOrNull<GroupFlashImage>()
-    FriendFlashImage -> firstIsInstanceOrNull<FriendFlashImage>()
-    else -> null
-} as M?
-
-/**
- * 使用 [Collection] 作为委托的 [MessageChain]
- */
-@PublishedApi
-internal class MessageChainImplByCollection constructor(
-    internal val delegate: Collection<SingleMessage> // 必须 constrainSingleMessages, 且为 immutable
-) : Message, Iterable<SingleMessage>, MessageChain {
-    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 }
-
-    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!!
-}
-
-/**
- * 使用 [Iterable] 作为委托的 [MessageChain]
- */
-@PublishedApi
-internal class MessageChainImplBySequence constructor(
-    delegate: Sequence<SingleMessage> // 可以有重复 ConstrainSingle
-) : Message, Iterable<SingleMessage>, MessageChain {
-    override val size: Int by lazy { collected.size }
-
-    /**
-     * [Sequence] 可能只能消耗一遍, 因此需要先转为 [List]
-     */
-    private val collected: List<SingleMessage> by lazy { delegate.constrainSingleMessages() }
-    override fun iterator(): Iterator<SingleMessage> = collected.iterator()
-
-    private var toStringTemp: String? = null
-        get() = field ?: this.joinToString("") { it.toString() }.also { field = it }
-
-    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]
- */
-@PublishedApi
-internal class SingleMessageChainImpl constructor(
-    internal val delegate: SingleMessage
-) : Message, Iterable<SingleMessage>, MessageChain {
-    override val size: Int get() = 1
-    override fun toString(): String = this.delegate.toString()
-    override fun contentToString(): String = this.delegate.contentToString()
-    override fun iterator(): Iterator<SingleMessage> = iterator { yield(delegate) }
-}
-
-// endregion

+ 264 - 0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/impl.kt

@@ -0,0 +1,264 @@
+/*
+ * Copyright 2020 Mamoe Technologies and contributors.
+ *
+ * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
+ * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
+ *
+ * https://github.com/mamoe/mirai/blob/master/LICENSE
+ */
+
+@file:Suppress("EXPERIMENTAL_API_USAGE")
+@file:JvmMultifileClass
+@file:JvmName("MessageUtils")
+
+package net.mamoe.mirai.message.data
+
+import net.mamoe.mirai.utils.MiraiExperimentalAPI
+import net.mamoe.mirai.utils.MiraiInternalAPI
+import kotlin.jvm.JvmMultifileClass
+import kotlin.jvm.JvmName
+import kotlin.jvm.JvmSynthetic
+
+/////////////////////////
+//// IMPLEMENTATIONS ////
+/////////////////////////
+
+
+@OptIn(MiraiInternalAPI::class)
+private fun Message.hasDuplicationOfConstrain(key: Message.Key<*>): 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")
+    }
+}
+
+@OptIn(MiraiInternalAPI::class)
+@JvmSynthetic
+@Suppress("DEPRECATION_ERROR")
+internal fun Message.followedByInternalForBinaryCompatibility(tail: Message): CombinedMessage {
+    return CombinedMessage(EmptyMessageChain, this.followedBy(tail))
+}
+
+@JvmSynthetic
+internal fun Message.followedByImpl(tail: Message): MessageChain {
+    when {
+        this is SingleMessage && tail is SingleMessage -> {
+            if (this is ConstrainSingle<*> && tail is ConstrainSingle<*>) {
+                if (this.key == tail.key)
+                    return SingleMessageChainImpl(tail)
+            }
+            return CombinedMessage(this, tail)
+        }
+
+        this is SingleMessage -> { // tail is not
+            tail as MessageChain
+
+            if (this is ConstrainSingle<*>) {
+                val key = this.key
+                if (tail.any { (it as? ConstrainSingle<*>)?.key == key }) {
+                    return tail
+                }
+            }
+            return CombinedMessage(this, tail)
+        }
+
+        tail is SingleMessage -> {
+            this as MessageChain
+
+            if (tail is ConstrainSingle<*> && this.hasDuplicationOfConstrain(tail.key)) {
+                val iterator = this.iterator()
+                var tailUsed = false
+                return MessageChainImplByCollection(
+                    constrainSingleMessagesImpl {
+                        if (iterator.hasNext()) {
+                            iterator.next()
+                        } else if (!tailUsed) {
+                            tailUsed = true
+                            tail
+                        } else null
+                    }
+                )
+            }
+
+            return CombinedMessage(this, tail)
+        }
+
+        else -> { // both chain
+            this as MessageChain
+            tail as MessageChain
+
+            var iterator = this.iterator()
+            var tailUsed = false
+            return MessageChainImplByCollection(
+                constrainSingleMessagesImpl {
+                    if (iterator.hasNext()) {
+                        iterator.next()
+                    } else if (!tailUsed) {
+                        tailUsed = true
+                        iterator = tail.iterator()
+                        iterator.next()
+                    } else null
+                }
+            )
+        }
+    }
+}
+
+
+@OptIn(MiraiExperimentalAPI::class)
+@JvmSynthetic
+internal fun Sequence<SingleMessage>.constrainSingleMessages(): List<SingleMessage> {
+    val iterator = this.iterator()
+    return constrainSingleMessagesImpl supplier@{
+        if (iterator.hasNext()) {
+            iterator.next()
+        } else null
+    }
+}
+
+@MiraiExperimentalAPI
+@JvmSynthetic
+internal inline fun constrainSingleMessagesImpl(iterator: () -> SingleMessage?): ArrayList<SingleMessage> {
+    val list = ArrayList<SingleMessage>()
+    var firstConstrainIndex = -1
+
+    var next: SingleMessage?
+    do {
+        next = iterator()
+        next?.let { singleMessage ->
+            if (singleMessage is ConstrainSingle<*>) {
+                if (firstConstrainIndex == -1) {
+                    firstConstrainIndex = list.size // we are going to add one
+                } else {
+                    val key = singleMessage.key
+                    val index = list.indexOfFirst(firstConstrainIndex) { it is ConstrainSingle<*> && it.key == key }
+                    if (index != -1) {
+                        list[index] = singleMessage
+                        return@let
+                    }
+                }
+            }
+
+            list.add(singleMessage)
+        } ?: return list
+    } while (true)
+}
+
+@JvmSynthetic
+@OptIn(MiraiExperimentalAPI::class)
+internal fun Iterable<SingleMessage>.constrainSingleMessages(): List<SingleMessage> {
+    val iterator = this.iterator()
+    return constrainSingleMessagesImpl supplier@{
+        if (iterator.hasNext()) {
+            iterator.next()
+        } else null
+    }
+}
+
+@JvmSynthetic
+internal inline fun <T> List<T>.indexOfFirst(offset: Int, predicate: (T) -> Boolean): Int {
+    for (index in offset..this.lastIndex) {
+        if (predicate(this[index]))
+            return index
+    }
+    return -1
+}
+
+
+@OptIn(MiraiExperimentalAPI::class)
+@JvmSynthetic
+@Suppress("UNCHECKED_CAST")
+internal fun <M : Message> MessageChain.firstOrNullImpl(key: Message.Key<M>): M? = when (key) {
+    At -> firstIsInstanceOrNull<At>()
+    AtAll -> firstIsInstanceOrNull<AtAll>()
+    PlainText -> firstIsInstanceOrNull<PlainText>()
+    Image -> firstIsInstanceOrNull<Image>()
+    OnlineImage -> firstIsInstanceOrNull<OnlineImage>()
+    OfflineImage -> firstIsInstanceOrNull<OfflineImage>()
+    GroupImage -> firstIsInstanceOrNull<GroupImage>()
+    FriendImage -> firstIsInstanceOrNull<FriendImage>()
+    Face -> firstIsInstanceOrNull<Face>()
+    QuoteReply -> firstIsInstanceOrNull<QuoteReply>()
+    MessageSource -> firstIsInstanceOrNull<MessageSource>()
+    OnlineMessageSource -> firstIsInstanceOrNull<OnlineMessageSource>()
+    OfflineMessageSource -> firstIsInstanceOrNull<OfflineMessageSource>()
+    OnlineMessageSource.Outgoing -> firstIsInstanceOrNull<OnlineMessageSource.Outgoing>()
+    OnlineMessageSource.Outgoing.ToGroup -> firstIsInstanceOrNull<OnlineMessageSource.Outgoing.ToGroup>()
+    OnlineMessageSource.Outgoing.ToFriend -> firstIsInstanceOrNull<OnlineMessageSource.Outgoing.ToFriend>()
+    OnlineMessageSource.Incoming -> firstIsInstanceOrNull<OnlineMessageSource.Incoming>()
+    OnlineMessageSource.Incoming.FromGroup -> firstIsInstanceOrNull<OnlineMessageSource.Incoming.FromGroup>()
+    OnlineMessageSource.Incoming.FromFriend -> firstIsInstanceOrNull<OnlineMessageSource.Incoming.FromFriend>()
+    OnlineMessageSource -> firstIsInstanceOrNull<OnlineMessageSource>()
+    XmlMessage -> firstIsInstanceOrNull<XmlMessage>()
+    JsonMessage -> firstIsInstanceOrNull<JsonMessage>()
+    RichMessage -> firstIsInstanceOrNull<RichMessage>()
+    LightApp -> firstIsInstanceOrNull<LightApp>()
+    PokeMessage -> firstIsInstanceOrNull<PokeMessage>()
+    HummerMessage -> firstIsInstanceOrNull<HummerMessage>()
+    FlashImage -> firstIsInstanceOrNull<FlashImage>()
+    GroupFlashImage -> firstIsInstanceOrNull<GroupFlashImage>()
+    FriendFlashImage -> firstIsInstanceOrNull<FriendFlashImage>()
+    else -> null
+} as M?
+
+/**
+ * 使用 [Collection] 作为委托的 [MessageChain]
+ */
+internal class MessageChainImplByCollection constructor(
+    internal val delegate: Collection<SingleMessage> // 必须 constrainSingleMessages, 且为 immutable
+) : Message, Iterable<SingleMessage>, MessageChain {
+    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 }
+
+    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!!
+}
+
+/**
+ * 使用 [Iterable] 作为委托的 [MessageChain]
+ */
+internal class MessageChainImplBySequence constructor(
+    delegate: Sequence<SingleMessage> // 可以有重复 ConstrainSingle
+) : Message, Iterable<SingleMessage>, MessageChain {
+    override val size: Int by lazy { collected.size }
+
+    /**
+     * [Sequence] 可能只能消耗一遍, 因此需要先转为 [List]
+     */
+    private val collected: List<SingleMessage> by lazy { delegate.constrainSingleMessages() }
+    override fun iterator(): Iterator<SingleMessage> = collected.iterator()
+
+    private var toStringTemp: String? = null
+        get() = field ?: this.joinToString("") { it.toString() }.also { field = it }
+
+    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, Iterable<SingleMessage>, MessageChain {
+    override val size: Int get() = 1
+    override fun toString(): String = this.delegate.toString()
+    override fun contentToString(): String = this.delegate.contentToString()
+    override fun iterator(): Iterator<SingleMessage> = iterator { yield(delegate) }
+}
+