mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-25 15:40:28 +08:00
Introduce PluginDataExtensions
This commit is contained in:
parent
a6aa160a97
commit
31cd77febf
@ -76,7 +76,7 @@ import kotlin.reflect.full.findAnnotation
|
||||
* @see JvmPlugin.reloadPluginData 通过 [JvmPlugin] 获取指定 [PluginData] 实例.
|
||||
* @see PluginDataStorage [PluginData] 存储仓库
|
||||
*/
|
||||
public interface PluginData : PluginDataExtensions {
|
||||
public interface PluginData {
|
||||
/**
|
||||
* 添加了追踪的 [ValueNode] 列表 (即使用 `by value()` 委托的属性), 即通过 `by value` 初始化的属性列表.
|
||||
*
|
||||
|
@ -1,59 +1,114 @@
|
||||
@file:Suppress("unused", "INAPPLICABLE_JVM_NAME")
|
||||
|
||||
package net.mamoe.mirai.console.data
|
||||
|
||||
import net.mamoe.mirai.console.internal.data.CompositeMapValueImpl
|
||||
import net.mamoe.mirai.console.internal.data.castOrInternalError
|
||||
import net.mamoe.mirai.console.internal.data.createCompositeMapValueImpl
|
||||
import net.mamoe.mirai.console.data.PluginDataExtensions.withDefault
|
||||
import net.mamoe.mirai.console.internal.data.ShadowMap
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
|
||||
@Suppress("INAPPLICABLE_JVM_NAME", "UNCHECKED_CAST")
|
||||
public interface PluginDataExtensions {
|
||||
/**
|
||||
* [PluginData] 相关一些扩展
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
public object PluginDataExtensions {
|
||||
|
||||
@JvmName("withDefaultImmutable")
|
||||
public fun <V, K> SerializerAwareValue<Map<K, V>>.withDefault(defaultValueComputer: (K) -> V): SerializerAwareValue<Map<K, V>> {
|
||||
/**
|
||||
* 创建一个代理对象, 当 [Map.get] 返回 `null` 时先放入一个 [LinkedHashMap], 再返回这个 [LinkedHashMap]
|
||||
* @see withDefault
|
||||
*/
|
||||
@JvmName("withEmptyDefaultMapImmutable")
|
||||
@JvmStatic
|
||||
public fun <K, InnerE, InnerV> SerializerAwareValue<MutableMap<K, Map<InnerE, InnerV>>>.withEmptyDefault(): SerializerAwareValue<MutableMap<K, Map<InnerE, InnerV>>> {
|
||||
return this.withDefault { LinkedHashMap() }
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个代理对象, 当 [Map.get] 返回 `null` 时先放入一个 [LinkedHashMap], 再返回这个 [LinkedHashMap]
|
||||
* @see withDefault
|
||||
*/
|
||||
@JvmName("withEmptyDefaultMap")
|
||||
@JvmStatic
|
||||
public fun <K, InnerE, InnerV> SerializerAwareValue<MutableMap<K, MutableMap<InnerE, InnerV>>>.withEmptyDefault(): SerializerAwareValue<MutableMap<K, MutableMap<InnerE, InnerV>>> {
|
||||
return this.withDefault { LinkedHashMap() }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建一个代理对象, 当 [Map.get] 返回 `null` 时先放入一个 [ArrayList], 再返回这个 [ArrayList]
|
||||
* @see withDefault
|
||||
*/
|
||||
@JvmName("withEmptyDefaultListImmutable")
|
||||
@JvmStatic
|
||||
public fun <K, E> SerializerAwareValue<MutableMap<K, List<E>>>.withEmptyDefault(): SerializerAwareValue<MutableMap<K, List<E>>> {
|
||||
return this.withDefault { ArrayList() }
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个代理对象, 当 [Map.get] 返回 `null` 时先放入一个 [ArrayList], 再返回这个 [ArrayList]
|
||||
* @see withDefault
|
||||
*/
|
||||
@JvmName("withEmptyDefaultList")
|
||||
@JvmStatic
|
||||
public fun <K, E> SerializerAwareValue<MutableMap<K, MutableList<E>>>.withEmptyDefault(): SerializerAwareValue<MutableMap<K, MutableList<E>>> {
|
||||
return this.withDefault { ArrayList() }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建一个代理对象, 当 [Map.get] 返回 `null` 时先放入一个 [LinkedHashSet], 再返回这个 [LinkedHashSet]
|
||||
* @see withDefault
|
||||
*/
|
||||
@JvmName("withEmptyDefaultSetImmutable")
|
||||
@JvmStatic
|
||||
public fun <K, E> SerializerAwareValue<MutableMap<K, Set<E>>>.withEmptyDefault(): SerializerAwareValue<MutableMap<K, Set<E>>> {
|
||||
return this.withDefault { LinkedHashSet() }
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个代理对象, 当 [Map.get] 返回 `null` 时先放入一个 [LinkedHashSet], 再返回这个 [LinkedHashSet]
|
||||
* @see withDefault
|
||||
*/
|
||||
@JvmName("withEmptyDefaultSet")
|
||||
@JvmStatic
|
||||
public fun <K, E> SerializerAwareValue<MutableMap<K, MutableSet<E>>>.withEmptyDefault(): SerializerAwareValue<MutableMap<K, MutableSet<E>>> {
|
||||
return this.withDefault { LinkedHashSet() }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建一个代理对象, 当 [Map.get] 返回 `null` 时先调用 [defaultValueComputer] 并放入 [Map], 再返回调用的返回值
|
||||
*/
|
||||
@JvmStatic
|
||||
@JvmName("withDefaultMapImmutable")
|
||||
public fun <K, V> SerializerAwareValue<Map<K, V>>.withDefault(defaultValueComputer: (K) -> V): SerializerAwareValue<Map<K, V>> {
|
||||
@Suppress("UNCHECKED_CAST") // magic
|
||||
return (this as SerializerAwareValue<MutableMap<K, V>>).withDefault(defaultValueComputer) as SerializerAwareValue<Map<K, V>>
|
||||
}
|
||||
|
||||
@JvmName("withDefaultImmutableMap")
|
||||
public fun <M : Map<K, V>, V : Map<*, *>, K> SerializerAwareValue<M>.withEmptyDefault(): SerializerAwareValue<M> {
|
||||
return this.withDefault { LinkedHashMap<Any?, Any?>() as V }
|
||||
}
|
||||
|
||||
@JvmName("withDefaultImmutableSet")
|
||||
public fun <M : Map<K, V>, V : Set<*>, K> SerializerAwareValue<M>.withEmptyDefault(): SerializerAwareValue<M> {
|
||||
return this.withDefault { LinkedHashSet<Any?>() as V }
|
||||
}
|
||||
|
||||
@JvmName("withDefaultImmutableList")
|
||||
public fun <M : Map<K, V>, V : List<*>, K> SerializerAwareValue<M>.withEmptyDefault(): SerializerAwareValue<M> {
|
||||
return this.withDefault { ArrayList<Any?>() as V }
|
||||
}
|
||||
|
||||
public fun <M : Map<K, V>, V, K> SerializerAwareValue<M>.withDefault(defaultValueComputer: (K) -> V): SerializerAwareValue<M> {
|
||||
val pluginData = this@PluginDataExtensions.castOrInternalError<PluginData>()
|
||||
|
||||
|
||||
val origin = (this as SerializableValue<M>).delegate.castOrInternalError<CompositeMapValueImpl<K, V>>()
|
||||
/**
|
||||
* 创建一个代理对象, 当 [Map.get] 返回 `null` 时先调用 [defaultValueComputer] 并放入 [Map], 再返回调用的返回值
|
||||
*/
|
||||
@JvmStatic
|
||||
@JvmName("withDefaultMap")
|
||||
public fun <K, V> SerializerAwareValue<MutableMap<K, V>>.withDefault(defaultValueComputer: (K) -> V): SerializerAwareValue<MutableMap<K, V>> {
|
||||
val origin = this
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return SerializableValue(
|
||||
object : CompositeMapValue<K, V> {
|
||||
private val instance = object : MutableMap<K, V> {
|
||||
override val size: Int get() = origin.value.size
|
||||
override fun containsKey(key: K): Boolean = origin.value.containsKey(key)
|
||||
override fun containsValue(value: V): Boolean = origin.value.containsValue(value)
|
||||
override fun isEmpty(): Boolean = origin.value.isEmpty()
|
||||
override val entries: MutableSet<MutableMap.MutableEntry<K, V>> get() = origin.value.entries as MutableSet<MutableMap.MutableEntry<K, V>>
|
||||
override val keys: MutableSet<K> get() = origin.value.keys as MutableSet<K>
|
||||
override val values: MutableCollection<V> get() = origin.value.values as MutableCollection<V>
|
||||
override fun clear() = (origin.value as MutableMap<K, V>).clear()
|
||||
override fun putAll(from: Map<out K, V>) = (origin.value as MutableMap<K, V>).putAll(from)
|
||||
override fun remove(key: K): V? = (origin.value as MutableMap<K, V>).remove(key)
|
||||
override fun put(key: K, value: V): V? = (origin.value as MutableMap<K, V>).put(key, value)
|
||||
private val instance = object : MutableMap<K, V>, AbstractMap<K, V>() {
|
||||
override val entries: MutableSet<MutableMap.MutableEntry<K, V>> get() = origin.value.entries
|
||||
override val keys: MutableSet<K> get() = origin.value.keys
|
||||
override val values: MutableCollection<V> get() = origin.value.values
|
||||
override fun clear() = origin.value.clear()
|
||||
override fun putAll(from: Map<out K, V>) = origin.value.putAll(from)
|
||||
override fun remove(key: K): V? = origin.value.remove(key)
|
||||
override fun put(key: K, value: V): V? = origin.value.put(key, value)
|
||||
|
||||
override fun get(key: K): V? {
|
||||
// the only difference
|
||||
val result = origin.value[key]
|
||||
if (result != null) {
|
||||
return result
|
||||
}
|
||||
if (result != null) return result
|
||||
put(key, defaultValueComputer(key))
|
||||
return origin.value[key]
|
||||
}
|
||||
@ -62,25 +117,65 @@ public interface PluginDataExtensions {
|
||||
override var value: Map<K, V>
|
||||
get() = instance
|
||||
set(value) {
|
||||
origin.value = value
|
||||
origin.value = value as MutableMap<K, V> // erased cast
|
||||
}
|
||||
} as Value<M>,
|
||||
} as Value<MutableMap<K, V>>, // erased cast
|
||||
this.serializer
|
||||
)
|
||||
return pluginData.createCompositeMapValueImpl(
|
||||
kToValue = origin.kToValue,
|
||||
vToValue = origin.vToValue,
|
||||
applyToShadowedMap = { theMap ->
|
||||
object : MutableMap<K, V> by theMap {
|
||||
override fun get(key: K): V? {
|
||||
val result = theMap[key]
|
||||
if (result != null) return result
|
||||
theMap[key] = defaultValueComputer(key)
|
||||
return theMap[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
).let { SerializableValue(it, serializer) } as SerializerAwareValue<M>
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 替换 [MutableMap] 的 key
|
||||
*/
|
||||
@JvmName("mapKeys")
|
||||
@JvmStatic
|
||||
public fun <OldK, NewK, V> SerializerAwareValue<MutableMap<OldK, V>>.mapKeys(
|
||||
oldToNew: (OldK) -> NewK,
|
||||
newToOld: (NewK) -> OldK,
|
||||
): SerializerAwareValue<MutableMap<NewK, V>> {
|
||||
val origin = this
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return SerializableValue(
|
||||
object : CompositeMapValue<NewK, V> {
|
||||
private val instance = ShadowMap({ origin.value }, oldToNew, newToOld, { it }, { it })
|
||||
|
||||
override var value: Map<NewK, V>
|
||||
get() = instance
|
||||
set(value) {
|
||||
origin.value = value.mapKeysTo(LinkedHashMap()) { it.key.let(newToOld) } // erased cast
|
||||
}
|
||||
} as Value<MutableMap<NewK, V>>, // erased cast
|
||||
this.serializer
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换 [Map] 的 key
|
||||
*/
|
||||
@JvmName("mapKeysImmutable")
|
||||
@JvmStatic
|
||||
public fun <OldK, NewK, V> SerializerAwareValue<Map<OldK, V>>.mapKeys(
|
||||
oldToNew: (OldK) -> NewK,
|
||||
newToOld: (NewK) -> OldK,
|
||||
): SerializerAwareValue<Map<NewK, V>> {
|
||||
val origin = this
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return SerializableValue(
|
||||
object : CompositeMapValue<NewK, V> {
|
||||
// casting Map to MutableMap is OK here, as we don't call mutable functions
|
||||
private val instance =
|
||||
ShadowMap({ origin.value as MutableMap<OldK, V> }, oldToNew, newToOld, { it }, { it })
|
||||
|
||||
override var value: Map<NewK, V>
|
||||
get() = instance
|
||||
set(value) {
|
||||
origin.value = value.mapKeysTo(LinkedHashMap()) { it.key.let(newToOld) } // erased cast
|
||||
}
|
||||
} as Value<Map<NewK, V>>, // erased cast
|
||||
this.serializer
|
||||
)
|
||||
}
|
||||
}
|
@ -240,10 +240,13 @@ public interface PrimitiveLongSetValue : PrimitiveSetValue<Long>
|
||||
* @see [CompositeMapValue]
|
||||
* @see [PrimitiveMapValue]
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
public interface MapValue<K, V> : CompositeValue<Map<K, V>>
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
public interface CompositeMapValue<K, V> : MapValue<K, V>
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
public interface PrimitiveMapValue<K, V> : MapValue<K, V>
|
||||
|
||||
|
||||
|
@ -20,20 +20,20 @@ import kotlin.reflect.KClass
|
||||
|
||||
|
||||
internal open class ShadowMap<K, V, KR, VR>(
|
||||
private val originMap: MutableMap<K, V>,
|
||||
private val originMapComputer: () -> MutableMap<K, V>,
|
||||
private val kTransform: (K) -> KR,
|
||||
private val kTransformBack: (KR) -> K,
|
||||
private val vTransform: (V) -> VR,
|
||||
private val vTransformBack: (VR) -> V
|
||||
) : MutableMap<KR, VR> {
|
||||
override val size: Int get() = originMap.size
|
||||
override fun containsKey(key: KR): Boolean = originMap.containsKey(key.let(kTransformBack))
|
||||
override fun containsValue(value: VR): Boolean = originMap.containsValue(value.let(vTransformBack))
|
||||
override fun get(key: KR): VR? = originMap[key.let(kTransformBack)]?.let(vTransform)
|
||||
override fun isEmpty(): Boolean = originMap.isEmpty()
|
||||
override val size: Int get() = originMapComputer().size
|
||||
override fun containsKey(key: KR): Boolean = originMapComputer().containsKey(key.let(kTransformBack))
|
||||
override fun containsValue(value: VR): Boolean = originMapComputer().containsValue(value.let(vTransformBack))
|
||||
override fun get(key: KR): VR? = originMapComputer()[key.let(kTransformBack)]?.let(vTransform)
|
||||
override fun isEmpty(): Boolean = originMapComputer().isEmpty()
|
||||
|
||||
override val entries: MutableSet<MutableMap.MutableEntry<KR, VR>>
|
||||
get() = originMap.entries.shadowMap(
|
||||
get() = originMapComputer().entries.shadowMap(
|
||||
transform = { entry: MutableMap.MutableEntry<K, V> ->
|
||||
object : MutableMap.MutableEntry<KR, VR> {
|
||||
override val key: KR get() = entry.key.let(kTransform)
|
||||
@ -66,30 +66,30 @@ internal open class ShadowMap<K, V, KR, VR>(
|
||||
}
|
||||
)
|
||||
override val keys: MutableSet<KR>
|
||||
get() = originMap.keys.shadowMap(kTransform, kTransformBack)
|
||||
get() = originMapComputer().keys.shadowMap(kTransform, kTransformBack)
|
||||
override val values: MutableCollection<VR>
|
||||
get() = originMap.values.shadowMap(vTransform, vTransformBack)
|
||||
get() = originMapComputer().values.shadowMap(vTransform, vTransformBack)
|
||||
|
||||
override fun clear() = originMap.clear()
|
||||
override fun clear() = originMapComputer().clear()
|
||||
override fun put(key: KR, value: VR): VR? =
|
||||
originMap.put(key.let(kTransformBack), value.let(vTransformBack))?.let(vTransform)
|
||||
originMapComputer().put(key.let(kTransformBack), value.let(vTransformBack))?.let(vTransform)
|
||||
|
||||
override fun putAll(from: Map<out KR, VR>) {
|
||||
from.forEach { (kr, vr) ->
|
||||
originMap[kr.let(kTransformBack)] = vr.let(vTransformBack)
|
||||
originMapComputer()[kr.let(kTransformBack)] = vr.let(vTransformBack)
|
||||
}
|
||||
}
|
||||
|
||||
override fun remove(key: KR): VR? = originMap.remove(key.let(kTransformBack))?.let(vTransform)
|
||||
override fun toString(): String = originMap.toString()
|
||||
override fun hashCode(): Int = originMap.hashCode()
|
||||
override fun remove(key: KR): VR? = originMapComputer().remove(key.let(kTransformBack))?.let(vTransform)
|
||||
override fun toString(): String = originMapComputer().toString()
|
||||
override fun hashCode(): Int = originMapComputer().hashCode()
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as ShadowMap<*, *, *, *>
|
||||
|
||||
if (originMap != other.originMap) return false
|
||||
if (originMapComputer != other.originMapComputer) return false
|
||||
if (kTransform != other.kTransform) return false
|
||||
if (kTransformBack != other.kTransformBack) return false
|
||||
if (vTransform != other.vTransform) return false
|
||||
@ -104,7 +104,7 @@ internal fun <K, V, KR, VR> MutableMap<K, V>.shadowMap(
|
||||
kTransformBack: (KR) -> K,
|
||||
vTransform: (V) -> VR,
|
||||
vTransformBack: (VR) -> V
|
||||
): MutableMap<KR, VR> = ShadowMap(this, kTransform, kTransformBack, vTransform, vTransformBack)
|
||||
): MutableMap<KR, VR> = ShadowMap({ this }, kTransform, kTransformBack, vTransform, vTransformBack)
|
||||
|
||||
internal inline fun <E, R> MutableCollection<E>.shadowMap(
|
||||
crossinline transform: (E) -> R,
|
||||
|
@ -17,6 +17,8 @@ import kotlinx.coroutines.SupervisorJob
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.data.*
|
||||
import net.mamoe.mirai.console.data.PluginDataExtensions.mapKeys
|
||||
import net.mamoe.mirai.console.data.PluginDataExtensions.withEmptyDefault
|
||||
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
|
||||
import net.mamoe.mirai.console.util.BotManager
|
||||
import net.mamoe.mirai.contact.User
|
||||
@ -44,7 +46,9 @@ internal object BotManagerImpl : BotManager {
|
||||
|
||||
internal object ManagersConfig : AutoSavePluginConfig() {
|
||||
private val managers by value<MutableMap<Long, MutableSet<Long>>>().withEmptyDefault()
|
||||
internal operator fun get(bot: Bot): MutableSet<Long> = managers[bot.id]!!
|
||||
.mapKeys(Bot::getInstance, Bot::id)
|
||||
|
||||
internal operator fun get(bot: Bot): MutableSet<Long> = managers[bot]!!
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user