mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-11 02:50:15 +08:00
Merge remote-tracking branch 'origin/reborn' into reborn
This commit is contained in:
commit
88afbb47d8
@ -9,6 +9,7 @@
|
||||
|
||||
package net.mamoe.mirai.console.codegen
|
||||
|
||||
import org.intellij.lang.annotations.Language
|
||||
import java.io.File
|
||||
|
||||
|
||||
@ -48,6 +49,9 @@ import kotlinx.serialization.builtins.*
|
||||
""".trimIndent()
|
||||
|
||||
fun genAllValueUseSite(): String = buildString {
|
||||
fun appendln(@Language("kt") code: String) {
|
||||
this.appendln(code.trimIndent())
|
||||
}
|
||||
// PRIMITIVE
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES) {
|
||||
appendln(genValueUseSite(number, number))
|
||||
@ -63,12 +67,54 @@ fun genAllValueUseSite(): String = buildString {
|
||||
appendln(genValueUseSite("Array<${number}>", "Typed${number}Array"))
|
||||
}
|
||||
|
||||
// PRIMITIVE LISTS
|
||||
// PRIMITIVE LISTS / PRIMITIVE SETS
|
||||
for (collectionName in listOf("List", "Set")) {
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES) {
|
||||
appendln(genValueUseSite("List<${number}>", "${number}List"))
|
||||
appendln(genValueUseSite("${collectionName}<${number}>", "${number}${collectionName}"))
|
||||
}
|
||||
}
|
||||
|
||||
// MUTABLE LIST / MUTABLE SET
|
||||
for (collectionName in listOf("List", "Set")) {
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES) {
|
||||
appendln()
|
||||
appendln(
|
||||
"""
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: Mutable${collectionName}<${number}>): Mutable${number}${collectionName}Value = valueImpl(default)
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// SPECIAL
|
||||
appendln()
|
||||
appendln(
|
||||
"""
|
||||
fun <T : Setting> Setting.value(default: T): Value<T> {
|
||||
require(this::class != default::class) {
|
||||
"Recursive nesting is prohibited"
|
||||
}
|
||||
return valueImpl(default)
|
||||
}
|
||||
|
||||
inline fun <T : Setting> Setting.value(default: T, crossinline initializer: T.() -> Unit): Value<T> =
|
||||
value(default).also { it.value.apply(initializer) }
|
||||
|
||||
inline fun <reified T : Setting> Setting.value(default: List<T>): SettingListValue<T> = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
inline fun <reified T : Setting> Setting.value(default: MutableList<T>): MutableSettingListValue<T> = valueImpl(default)
|
||||
|
||||
|
||||
inline fun <reified T : Setting> Setting.value(default: Set<T>): SettingSetValue<T> = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
inline fun <reified T : Setting> Setting.value(default: MutableSet<T>): MutableSettingSetValue<T> = valueImpl(default)
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
fun genValueUseSite(kotlinTypeName: String, miraiValueName: String): String =
|
||||
"""
|
||||
fun Setting.value(default: $kotlinTypeName): ${miraiValueName}Value = valueImpl(default)
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
package net.mamoe.mirai.console.codegen
|
||||
|
||||
import org.intellij.lang.annotations.Language
|
||||
import java.io.File
|
||||
|
||||
|
||||
@ -44,31 +45,138 @@ package net.mamoe.mirai.console.setting
|
||||
""".trimIndent()
|
||||
|
||||
private val IMPORTS = """
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.builtins.*
|
||||
""".trimIndent()
|
||||
|
||||
fun genAllValueImpl(): String = buildString {
|
||||
fun appendln(@Language("kt") code: String) {
|
||||
this.appendln(code.trimIndent())
|
||||
}
|
||||
|
||||
// PRIMITIVE
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES) {
|
||||
appendln(genValueImpl(number, number, "$number.serializer()", false))
|
||||
appendln()
|
||||
}
|
||||
|
||||
// PRIMITIVE ARRAYS
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES.filterNot { it == "String" }) {
|
||||
appendln(genValueImpl("${number}Array", "${number}Array", "${number}ArraySerializer()", true))
|
||||
appendln()
|
||||
}
|
||||
|
||||
// TYPED ARRAYS
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES) {
|
||||
appendln(genValueImpl("Array<${number}>", "Typed${number}Array", "ArraySerializer(${number}.serializer())", true))
|
||||
appendln(
|
||||
genValueImpl(
|
||||
"Array<${number}>",
|
||||
"Typed${number}Array",
|
||||
"ArraySerializer(${number}.serializer())",
|
||||
true
|
||||
)
|
||||
)
|
||||
appendln()
|
||||
}
|
||||
|
||||
// PRIMITIVE LISTS
|
||||
// PRIMITIVE LISTS / SETS
|
||||
for (collectionName in listOf("List", "Set")) {
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES) {
|
||||
appendln(genValueImpl("List<${number}>", "${number}List", "ListSerializer(${number}.serializer())", false))
|
||||
appendln(
|
||||
genValueImpl(
|
||||
"${collectionName}<${number}>",
|
||||
"${number}${collectionName}",
|
||||
"${collectionName}Serializer(${number}.serializer())",
|
||||
false
|
||||
)
|
||||
)
|
||||
appendln()
|
||||
}
|
||||
}
|
||||
|
||||
appendln()
|
||||
|
||||
// MUTABLE LIST / MUTABLE SET
|
||||
|
||||
for (collectionName in listOf("List", "Set")) {
|
||||
for (number in NUMBERS + OTHER_PRIMITIVES) {
|
||||
appendln(
|
||||
"""
|
||||
@JvmName("valueImplMutable${number}${collectionName}")
|
||||
internal fun Setting.valueImpl(
|
||||
default: Mutable${collectionName}<${number}>
|
||||
): Mutable${number}${collectionName}Value {
|
||||
var internalValue: Mutable${collectionName}<${number}> = default
|
||||
|
||||
return object : Mutable${number}${collectionName}Value(), Mutable${collectionName}<${number}> by dynamicMutable${collectionName}({ internalValue }) {
|
||||
override var value: Mutable${collectionName}<${number}>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
private inline val `this` get() = this
|
||||
|
||||
override val serializer: KSerializer<Mutable${collectionName}<${number}>> = object : KSerializer<Mutable${collectionName}<${number}>> {
|
||||
private val delegate = ${collectionName}Serializer(${number}.serializer())
|
||||
override val descriptor: SerialDescriptor = delegate.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): Mutable${collectionName}<${number}> {
|
||||
return delegate.deserialize(decoder).toMutable${collectionName}().observable {
|
||||
onElementChanged(`this`)
|
||||
}
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: Mutable${collectionName}<${number}>) {
|
||||
delegate.serialize(encoder, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
appendln()
|
||||
}
|
||||
}
|
||||
|
||||
appendln()
|
||||
|
||||
|
||||
appendln(
|
||||
"""
|
||||
internal fun <T : Setting> Setting.valueImpl(default: T): Value<T> {
|
||||
return object : SettingValue<T>() {
|
||||
private var internalValue: T = default
|
||||
override var value: T
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = object : KSerializer<T>{
|
||||
override val descriptor: SerialDescriptor
|
||||
get() = internalValue.updaterSerializer.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): T {
|
||||
internalValue.updaterSerializer.deserialize(decoder)
|
||||
return internalValue
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: T) {
|
||||
internalValue.updaterSerializer.serialize(encoder, SettingSerializerMark)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
fun genValueImpl(kotlinTypeName: String, miraiValueName: String, serializer: String, isArray: Boolean): String =
|
||||
"""
|
||||
internal fun Setting.valueImpl(default: ${kotlinTypeName}): ${miraiValueName}Value {
|
||||
@ -92,10 +200,7 @@ fun genValueImpl(kotlinTypeName: String, miraiValueName: String, serializer: Str
|
||||
""".trim()
|
||||
}
|
||||
}
|
||||
override val serializer = ${serializer}.bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
override val serializer = $serializer
|
||||
}
|
||||
}
|
||||
""".trimIndent() + "\n"
|
||||
|
@ -7,6 +7,7 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
@file:Suppress("ClassName", "unused")
|
||||
|
||||
package net.mamoe.mirai.console.codegen
|
||||
|
||||
import org.intellij.lang.annotations.Language
|
||||
@ -20,7 +21,7 @@ fun main() {
|
||||
}.writeText(genPublicApi())
|
||||
}
|
||||
|
||||
internal const val COPYRIGHT = """
|
||||
internal val COPYRIGHT = """
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
@ -29,7 +30,7 @@ internal const val COPYRIGHT = """
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
"""
|
||||
""".trim()
|
||||
|
||||
internal val NUMBERS = listOf(
|
||||
"Int",
|
||||
@ -86,11 +87,23 @@ fun genPublicApi() = buildString {
|
||||
sealed class Value<T : Any> : ReadWriteProperty<Setting, T> {
|
||||
abstract var value: T
|
||||
|
||||
/**
|
||||
* 用于更新 [value] 的序列化器
|
||||
*/
|
||||
abstract val serializer: KSerializer<T>
|
||||
override fun getValue(thisRef: Setting, property: KProperty<*>): T = value
|
||||
override fun setValue(thisRef: Setting, property: KProperty<*>, value: T) {
|
||||
this.value = value
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other==null)return false
|
||||
if (other::class != this::class) return false
|
||||
other as Value<*>
|
||||
return other.value == this.value
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = value.hashCode()
|
||||
}
|
||||
"""
|
||||
)
|
||||
@ -176,11 +189,12 @@ sealed class Value<T : Any> : ReadWriteProperty<Setting, T> {
|
||||
|
||||
appendln()
|
||||
|
||||
// TYPED LISTS
|
||||
// TYPED LISTS / SETS
|
||||
for (collectionName in listOf("List", "Set")) {
|
||||
|
||||
appendln(
|
||||
"""
|
||||
sealed class ListValue<E> : Value<List<E>>(), Iterable<E>{
|
||||
sealed class ${collectionName}Value<E> : Value<${collectionName}<E>>(), Iterable<E>{
|
||||
override fun iterator() = this.value.iterator()
|
||||
}
|
||||
"""
|
||||
@ -188,52 +202,70 @@ sealed class Value<T : Any> : ReadWriteProperty<Setting, T> {
|
||||
|
||||
for (number in (NUMBERS + OTHER_PRIMITIVES)) {
|
||||
val template = """
|
||||
abstract class ${number}ListValue internal constructor() : ListValue<${number}>()
|
||||
abstract class ${number}${collectionName}Value internal constructor() : ${collectionName}Value<${number}>()
|
||||
"""
|
||||
|
||||
appendln(template)
|
||||
}
|
||||
|
||||
appendln()
|
||||
// SETTING
|
||||
appendln(
|
||||
"""
|
||||
abstract class Setting${collectionName}Value<T: Setting> internal constructor() : Value<${collectionName}<T>>(), ${collectionName}<T>
|
||||
"""
|
||||
)
|
||||
appendln()
|
||||
}
|
||||
|
||||
// FOR COMPLEX TYPES
|
||||
// SETTING VALUE
|
||||
|
||||
appendln(
|
||||
"""
|
||||
abstract class SettingValue<T : Setting> internal constructor() : Value<T>()
|
||||
|
||||
internal fun <T : Setting> Setting.valueImpl(default: T): Value<T> {
|
||||
return object : SettingValue<T>() {
|
||||
private var internalValue: T = default
|
||||
override var value: T
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = object : KSerializer<T>{
|
||||
override val descriptor: SerialDescriptor
|
||||
get() = internalValue.updaterSerializer.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): T {
|
||||
internalValue.updaterSerializer.deserialize(decoder)
|
||||
return internalValue
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: T) {
|
||||
internalValue.updaterSerializer.serialize(encoder, SettingSerializerMark)
|
||||
}
|
||||
|
||||
}.bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
appendln()
|
||||
|
||||
// MUTABLE LIST / MUTABLE SET
|
||||
for (collectionName in listOf("List", "Set")) {
|
||||
appendln(
|
||||
"""
|
||||
abstract class Mutable${collectionName}Value<T : Any> internal constructor() : Value<Mutable${collectionName}<Value<T>>>(), Mutable${collectionName}<T>
|
||||
"""
|
||||
)
|
||||
|
||||
appendln()
|
||||
|
||||
for (number in (NUMBERS + OTHER_PRIMITIVES)) {
|
||||
appendln(
|
||||
"""
|
||||
abstract class Mutable${number}${collectionName}Value internal constructor() : Value<Mutable${collectionName}<${number}>>(), Mutable${collectionName}<${number}>
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
appendln()
|
||||
// SETTING
|
||||
appendln(
|
||||
"""
|
||||
abstract class MutableSetting${collectionName}Value<T: Setting> internal constructor() : Value<Mutable${collectionName}<T>>(), Mutable${collectionName}<T>
|
||||
"""
|
||||
)
|
||||
appendln()
|
||||
}
|
||||
|
||||
appendln()
|
||||
// DYNAMIC
|
||||
|
||||
appendln(
|
||||
"""
|
||||
/**
|
||||
* 只引用这个对象, 而不跟踪其成员.
|
||||
* 仅适用于基础类型, 用于 mutable list/map 等情况; 或标注了 [Serializable] 的类.
|
||||
*/
|
||||
abstract class DynamicReferenceValue<T : Any> internal constructor() : Value<T>()
|
||||
"""
|
||||
)
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.setting
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import net.mamoe.yamlkt.Yaml
|
||||
import net.mamoe.yamlkt.YamlConfiguration
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
|
||||
internal abstract class AbstractSetting {
|
||||
|
||||
@JvmField
|
||||
internal var valueList: MutableList<Pair<Value<*>, KProperty<*>>> = mutableListOf()
|
||||
|
||||
@JvmField
|
||||
internal var built: Boolean = false
|
||||
|
||||
internal val updaterSerializer: KSerializer<SettingSerializerMark> by lazy {
|
||||
built = true
|
||||
SettingUpdaterSerializer(this as Setting)
|
||||
}
|
||||
|
||||
internal val kotlinSerializer: KSerializer<Setting> by lazy {
|
||||
object : KSerializer<Setting> {
|
||||
override val descriptor: SerialDescriptor
|
||||
get() = this@AbstractSetting.updaterSerializer.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): Setting {
|
||||
this@AbstractSetting.updaterSerializer.deserialize(decoder)
|
||||
return this@AbstractSetting as Setting
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: Setting) {
|
||||
this@AbstractSetting.updaterSerializer.serialize(encoder, SettingSerializerMark)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun onElementChanged(value: Value<*>) {
|
||||
println("my value changed!")
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
internal val yaml =
|
||||
Yaml(
|
||||
configuration = YamlConfiguration(
|
||||
nonStrictNullability = true,
|
||||
nonStrictNumber = true,
|
||||
stringSerialization = YamlConfiguration.StringSerialization.NONE,
|
||||
classSerialization = YamlConfiguration.MapSerialization.FLOW_MAP,
|
||||
listSerialization = YamlConfiguration.ListSerialization.FLOW_SEQUENCE
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal class SettingUpdaterSerializer(
|
||||
private val instance: Setting
|
||||
) : KSerializer<SettingSerializerMark> {
|
||||
override val descriptor: SerialDescriptor by lazy {
|
||||
SerialDescriptor(instance.serialName) {
|
||||
for ((value, property) in instance.valueList) {
|
||||
element(property.serialNameOrPropertyName, value.serializer.descriptor, annotations, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST") // erased, no problem.
|
||||
override fun deserialize(decoder: Decoder): SettingSerializerMark = decoder.decodeStructure(descriptor) {
|
||||
if (this.decodeSequentially()) {
|
||||
instance.valueList.forEachIndexed { index, (value, _) ->
|
||||
val v = value as Value<Any>
|
||||
v.value = this.decodeSerializableElement(
|
||||
value.serializer.descriptor,
|
||||
index,
|
||||
v.serializer
|
||||
)
|
||||
}
|
||||
} else {
|
||||
while (true) {
|
||||
val index = this.decodeElementIndex(descriptor)
|
||||
if (index == CompositeDecoder.READ_DONE) return@decodeStructure SettingSerializerMark
|
||||
val value = instance.valueList[index].first
|
||||
|
||||
this.decodeSerializableElement(
|
||||
descriptor,
|
||||
index,
|
||||
value.serializer
|
||||
)
|
||||
}
|
||||
}
|
||||
SettingSerializerMark
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: SettingSerializerMark) = encoder.encodeStructure(descriptor) {
|
||||
instance.valueList.forEachIndexed { index, (value, _) ->
|
||||
@Suppress("UNCHECKED_CAST") // erased, no problem.
|
||||
this.encodeSerializableElement(
|
||||
descriptor,
|
||||
index,
|
||||
value.serializer as KSerializer<Any>,
|
||||
value.value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal object SettingSerializerMark
|
||||
|
||||
internal val KProperty<*>.serialNameOrPropertyName: String get() = this.findAnnotation<SerialName>()?.value ?: this.name
|
||||
|
||||
internal inline fun <E> KSerializer<E>.bind(
|
||||
crossinline setter: (E) -> Unit,
|
||||
crossinline getter: () -> E
|
||||
): KSerializer<E> {
|
||||
return object : KSerializer<E> {
|
||||
override val descriptor: SerialDescriptor get() = this@bind.descriptor
|
||||
override fun deserialize(decoder: Decoder): E = this@bind.deserialize(decoder).also { setter(it) }
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun serialize(encoder: Encoder, value: E) =
|
||||
this@bind.serialize(encoder, getter())
|
||||
}
|
||||
}
|
@ -11,35 +11,18 @@
|
||||
|
||||
package net.mamoe.mirai.console.setting
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import net.mamoe.yamlkt.Yaml
|
||||
import net.mamoe.yamlkt.YamlConfiguration
|
||||
import net.mamoe.yamlkt.YamlConfiguration.ListSerialization.FLOW_SEQUENCE
|
||||
import net.mamoe.yamlkt.YamlConfiguration.MapSerialization.FLOW_MAP
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
|
||||
internal inline fun <E> KSerializer<E>.bind(
|
||||
crossinline setter: (E) -> Unit,
|
||||
crossinline getter: () -> E
|
||||
): KSerializer<E> {
|
||||
return object : KSerializer<E> {
|
||||
override val descriptor: SerialDescriptor get() = this@bind.descriptor
|
||||
override fun deserialize(decoder: Decoder): E = this@bind.deserialize(decoder).also { setter(it) }
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun serialize(encoder: Encoder, value: E) =
|
||||
this@bind.serialize(encoder, getter())
|
||||
}
|
||||
}
|
||||
|
||||
typealias SerialName = kotlinx.serialization.SerialName
|
||||
|
||||
/**
|
||||
* 配置的基类
|
||||
* 配置的基类. 所有配置必须拥有一个无参构造器, 以用于在 [MutableList] 与 [MutableMap] 中动态识别类型
|
||||
*/
|
||||
abstract class Setting {
|
||||
@Suppress("EXPOSED_SUPER_CLASS")
|
||||
abstract class Setting : AbstractSetting() {
|
||||
open val serialName: String
|
||||
get() = this::class.findAnnotation<SerialName>()?.value
|
||||
?: this::class.qualifiedName
|
||||
@ -56,103 +39,9 @@ abstract class Setting {
|
||||
return this
|
||||
}
|
||||
|
||||
@JvmField
|
||||
internal var valueList: MutableList<Pair<Value<*>, KProperty<*>>> = mutableListOf()
|
||||
private var built: Boolean = false
|
||||
|
||||
internal val updaterSerializer: KSerializer<SettingSerializerMark> by lazy {
|
||||
built = true
|
||||
SettingUpdaterSerializer(this)
|
||||
}
|
||||
|
||||
internal val kotlinSerializer: KSerializer<Setting> by lazy {
|
||||
object : KSerializer<Setting> {
|
||||
override val descriptor: SerialDescriptor
|
||||
get() = this@Setting.updaterSerializer.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): Setting {
|
||||
this@Setting.updaterSerializer.deserialize(decoder)
|
||||
return this@Setting
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: Setting) {
|
||||
this@Setting.updaterSerializer.serialize(encoder, SettingSerializerMark)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun onElementChanged(value: Value<*>) {
|
||||
println("my value changed!")
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val yaml =
|
||||
Yaml(configuration = YamlConfiguration(classSerialization = FLOW_MAP, listSerialization = FLOW_SEQUENCE))
|
||||
}
|
||||
|
||||
override fun toString(): String = yaml.stringify(this.serializer, this)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val <T : Setting> T.serializer: KSerializer<T>
|
||||
get() = kotlinSerializer as KSerializer<T>
|
||||
|
||||
internal class SettingUpdaterSerializer(
|
||||
private val instance: Setting
|
||||
) : KSerializer<SettingSerializerMark> {
|
||||
override val descriptor: SerialDescriptor by lazy {
|
||||
SerialDescriptor(instance.serialName) {
|
||||
for ((value, property) in instance.valueList) {
|
||||
element(property.serialNameOrPropertyName, value.serializer.descriptor, annotations, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST") // erased, no problem.
|
||||
override fun deserialize(decoder: Decoder): SettingSerializerMark = decoder.decodeStructure(descriptor) {
|
||||
if (this.decodeSequentially()) {
|
||||
instance.valueList.forEachIndexed { index, (value, _) ->
|
||||
this.decodeSerializableElement(
|
||||
value.serializer.descriptor,
|
||||
index,
|
||||
value.serializer as KSerializer<Any>
|
||||
)
|
||||
}
|
||||
} else {
|
||||
while (true) {
|
||||
val index = this.decodeElementIndex(descriptor)
|
||||
if (index == CompositeDecoder.READ_DONE) return@decodeStructure SettingSerializerMark
|
||||
val value = instance.valueList[index].first
|
||||
|
||||
this.decodeSerializableElement(
|
||||
descriptor,
|
||||
index,
|
||||
value.serializer
|
||||
)
|
||||
}
|
||||
}
|
||||
SettingSerializerMark
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: SettingSerializerMark) = encoder.encodeStructure(descriptor) {
|
||||
instance.valueList.forEachIndexed { index, (value, _) ->
|
||||
@Suppress("UNCHECKED_CAST") // erased, no problem.
|
||||
this.encodeSerializableElement(
|
||||
descriptor,
|
||||
index,
|
||||
value.serializer as KSerializer<Any>,
|
||||
value.value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal object SettingSerializerMark
|
||||
|
||||
internal val KProperty<*>.serialNameOrPropertyName: String get() = this.findAnnotation<SerialName>()?.value ?: this.name
|
||||
|
||||
|
||||
fun <T : Setting> Setting.value(default: T): Value<T> = valueImpl(default)
|
||||
inline fun <T : Setting> Setting.value(default: T, crossinline initializer: T.() -> Unit): Value<T> =
|
||||
value(default).also { it.value.apply(initializer) }
|
||||
|
@ -0,0 +1,313 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.setting
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.builtins.ListSerializer
|
||||
import kotlinx.serialization.builtins.SetSerializer
|
||||
import net.mamoe.yamlkt.YamlDynamicSerializer
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.full.createInstance
|
||||
|
||||
/// region MUTABLE LIST
|
||||
|
||||
@PublishedApi
|
||||
@JvmName("valueImplSetting")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal inline fun <reified T : Setting> Setting.valueImpl(
|
||||
default: List<T>
|
||||
): SettingListValue<T> = valueImpl(default, T::class.createInstance().serializer)
|
||||
|
||||
@PublishedApi
|
||||
@JvmName("valueImplSettingMutable")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal inline fun <reified T : Setting> Setting.valueImpl(
|
||||
default: MutableList<T>
|
||||
): MutableSettingListValue<T> = valueImpl(default, T::class.createInstance().serializer)
|
||||
|
||||
|
||||
/*
|
||||
@PublishedApi
|
||||
@JvmName("valueImpl1")
|
||||
internal fun <T : Any> Setting.valueImpl(
|
||||
default: MutableList<T>,
|
||||
valueMapper: (T) -> Value<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): MutableListValue<T> = valueImpl(default.mapTo(mutableListOf(), valueMapper), valueMapper, elementSerializer)
|
||||
*/
|
||||
internal fun <T : Any> Setting.valueImpl(
|
||||
default: MutableList<Value<T>>,
|
||||
valueMapper: (T) -> Value<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): MutableListValue<T> {
|
||||
var internalValue: MutableList<Value<T>> = default
|
||||
|
||||
fun updateShadow(): MutableList<T> =
|
||||
internalValue.shadowMap(transform = { it.value }, transformBack = { valueMapper(it) })
|
||||
|
||||
var shadowed: MutableList<T> = updateShadow()
|
||||
return object : MutableListValue<T>(), MutableList<T> by dynamicMutableList({ shadowed }) {
|
||||
override var value: MutableList<Value<T>>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
shadowed = updateShadow()
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer: KSerializer<MutableList<Value<T>>> = object : KSerializer<MutableList<Value<T>>> {
|
||||
private val delegate = ListSerializer(elementSerializer)
|
||||
override val descriptor: SerialDescriptor = delegate.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): MutableList<Value<T>> {
|
||||
return delegate.deserialize(decoder).mapTo(mutableListOf(), valueMapper)
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: MutableList<Value<T>>) {
|
||||
delegate.serialize(encoder, value.map { it.value })
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T : Setting> Setting.valueImpl(
|
||||
default: MutableList<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): MutableSettingListValue<T> {
|
||||
var internalValue: MutableList<T> = default
|
||||
|
||||
return object : MutableSettingListValue<T>(), MutableList<T> by dynamicMutableList({ internalValue }) {
|
||||
override var value: MutableList<T>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer: KSerializer<MutableList<T>> = object : KSerializer<MutableList<T>> {
|
||||
private val delegate = ListSerializer(elementSerializer)
|
||||
override val descriptor: SerialDescriptor = delegate.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): MutableList<T> {
|
||||
return delegate.deserialize(decoder).toMutableList() // TODO: 2020/5/17 ATTACH OBSERVER
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: MutableList<T>) {
|
||||
delegate.serialize(encoder, value)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T : Setting> Setting.valueImpl(
|
||||
default: List<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): SettingListValue<T> {
|
||||
var internalValue: List<T> = default
|
||||
|
||||
return object : SettingListValue<T>(), List<T> by dynamicList({ internalValue }) {
|
||||
override var value: List<T>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer: KSerializer<List<T>> = object : KSerializer<List<T>> {
|
||||
private val delegate = ListSerializer(elementSerializer)
|
||||
override val descriptor: SerialDescriptor = delegate.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): List<T> {
|
||||
return delegate.deserialize(decoder) // TODO: 2020/5/17 ATTACH OBSERVER
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: List<T>) {
|
||||
delegate.serialize(encoder, value)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T : Setting> Setting.valueImpl(
|
||||
default: Set<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): SettingSetValue<T> {
|
||||
var internalValue: Set<T> = default
|
||||
|
||||
return object : SettingSetValue<T>(), Set<T> by dynamicSet({ internalValue }) {
|
||||
override var value: Set<T>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer: KSerializer<Set<T>> = object : KSerializer<Set<T>> {
|
||||
private val delegate = SetSerializer(elementSerializer)
|
||||
override val descriptor: SerialDescriptor = delegate.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): Set<T> {
|
||||
return delegate.deserialize(decoder) // TODO: 2020/5/17 ATTACH OBSERVER
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: Set<T>) {
|
||||
delegate.serialize(encoder, value)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T : Setting> Setting.valueImpl(
|
||||
default: MutableSet<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): MutableSettingSetValue<T> {
|
||||
var internalValue: MutableSet<T> = default
|
||||
|
||||
return object : MutableSettingSetValue<T>(), MutableSet<T> by dynamicMutableSet({ internalValue }) {
|
||||
override var value: MutableSet<T>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer: KSerializer<MutableSet<T>> = object : KSerializer<MutableSet<T>> {
|
||||
private val delegate = SetSerializer(elementSerializer)
|
||||
override val descriptor: SerialDescriptor = delegate.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): MutableSet<T> {
|
||||
return delegate.deserialize(decoder).toMutableSet() // TODO: 2020/5/17 ATTACH OBSERVER
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: MutableSet<T>) {
|
||||
delegate.serialize(encoder, value)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
// region MUTABLE SET
|
||||
|
||||
@PublishedApi
|
||||
@JvmName("valueImplSetting")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal inline fun <reified T : Setting> Setting.valueImpl(
|
||||
default: Set<T>
|
||||
): SettingSetValue<T> = valueImpl(default, T::class.createInstance().serializer)
|
||||
|
||||
@PublishedApi
|
||||
@JvmName("valueImplSettingMutable")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal inline fun <reified T : Setting> Setting.valueImpl(
|
||||
default: MutableSet<T>
|
||||
): MutableSettingSetValue<T> = valueImpl(default, T::class.createInstance().serializer)
|
||||
|
||||
/*
|
||||
@JvmName("valueImpl1")
|
||||
@PublishedApi
|
||||
internal fun <T : Any> Setting.valueImpl(
|
||||
default: MutableSet<T>,
|
||||
valueMapper: (T) -> Value<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): MutableSetValue<T> = valueImpl(default.mapTo(mutableSetOf(), valueMapper), valueMapper, elementSerializer)
|
||||
*/
|
||||
@JvmName("valueImplMutable")
|
||||
internal fun <T : Any> Setting.valueImpl(
|
||||
default: MutableSet<Value<T>>,
|
||||
valueMapper: (T) -> Value<T>,
|
||||
elementSerializer: KSerializer<T>
|
||||
): MutableSetValue<T> {
|
||||
var internalValue: MutableSet<Value<T>> = default
|
||||
|
||||
fun updateShadow(): MutableSet<T> =
|
||||
internalValue.shadowMap(transform = { it.value }, transformBack = { valueMapper(it) })
|
||||
|
||||
var shadowed: MutableSet<T> = updateShadow()
|
||||
return object : MutableSetValue<T>(), MutableSet<T> by dynamicMutableSet({ shadowed }) {
|
||||
override var value: MutableSet<Value<T>>
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
shadowed = updateShadow()
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer: KSerializer<MutableSet<Value<T>>> = object : KSerializer<MutableSet<Value<T>>> {
|
||||
private val delegate = SetSerializer(elementSerializer)
|
||||
override val descriptor: SerialDescriptor = delegate.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): MutableSet<Value<T>> {
|
||||
return delegate.deserialize(decoder).mapTo(mutableSetOf(), valueMapper)
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: MutableSet<Value<T>>) {
|
||||
delegate.serialize(encoder, value.mapTo(mutableSetOf()) { it.value })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region DYNAMIC PRIMITIVES AND SERIALIZABLE
|
||||
|
||||
/**
|
||||
* For primitives and serializable only
|
||||
*/
|
||||
@PublishedApi
|
||||
internal inline fun <reified T : Any> Setting.valueImpl(default: T): Value<T> =
|
||||
valueImpl(default, T::class)
|
||||
|
||||
@PublishedApi
|
||||
internal fun <T : Any> Setting.valueImpl(default: T, clazz: KClass<out T>): Value<T> {
|
||||
if (default is Setting) @Suppress("UNCHECKED_CAST") return valueImpl(default as Setting) as Value<T>
|
||||
|
||||
@OptIn(ImplicitReflectionSerializer::class)
|
||||
requireNotNull(clazz.serializerOrNull()) {
|
||||
"${clazz.qualifiedName} is not serializable"
|
||||
}
|
||||
return object : DynamicReferenceValue<T>() {
|
||||
override var value: T = default
|
||||
override val serializer: KSerializer<T>
|
||||
get() = object : KSerializer<T> {
|
||||
override val descriptor: SerialDescriptor
|
||||
get() = YamlDynamicSerializer.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): T {
|
||||
return YamlDynamicSerializer.deserialize(decoder).smartCastPrimitive(clazz)
|
||||
}
|
||||
|
||||
@OptIn(ImplicitReflectionSerializer::class)
|
||||
override fun serialize(encoder: Encoder, value: T) {
|
||||
YamlDynamicSerializer.serialize(encoder, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
@ -52,4 +51,88 @@ fun Setting.value(default: List<Double>): DoubleListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Boolean>): BooleanListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<Char>): CharListValue = valueImpl(default)
|
||||
fun Setting.value(default: List<String>): StringListValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Int>): IntSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Short>): ShortSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Byte>): ByteSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Long>): LongSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Float>): FloatSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Double>): DoubleSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Boolean>): BooleanSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<Char>): CharSetValue = valueImpl(default)
|
||||
fun Setting.value(default: Set<String>): StringSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Int>): MutableIntListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Short>): MutableShortListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Byte>): MutableByteListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Long>): MutableLongListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Float>): MutableFloatListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Double>): MutableDoubleListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Boolean>): MutableBooleanListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<Char>): MutableCharListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableList<String>): MutableStringListValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Int>): MutableIntSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Short>): MutableShortSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Byte>): MutableByteSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Long>): MutableLongSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Float>): MutableFloatSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Double>): MutableDoubleSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Boolean>): MutableBooleanSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<Char>): MutableCharSetValue = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
fun Setting.value(default: MutableSet<String>): MutableStringSetValue = valueImpl(default)
|
||||
|
||||
fun <T : Setting> Setting.value(default: T): Value<T> {
|
||||
require(this::class != default::class) {
|
||||
"Recursive nesting is prohibited"
|
||||
}
|
||||
return valueImpl(default)
|
||||
}
|
||||
|
||||
inline fun <T : Setting> Setting.value(default: T, crossinline initializer: T.() -> Unit): Value<T> =
|
||||
value(default).also { it.value.apply(initializer) }
|
||||
|
||||
inline fun <reified T : Setting> Setting.value(default: List<T>): SettingListValue<T> = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
inline fun <reified T : Setting> Setting.value(default: MutableList<T>): MutableSettingListValue<T> = valueImpl(default)
|
||||
|
||||
|
||||
inline fun <reified T : Setting> Setting.value(default: Set<T>): SettingSetValue<T> = valueImpl(default)
|
||||
|
||||
@JvmName("valueMutable")
|
||||
inline fun <reified T : Setting> Setting.value(default: MutableSet<T>): MutableSettingSetValue<T> = valueImpl(default)
|
||||
|
||||
|
@ -9,15 +9,12 @@
|
||||
|
||||
package net.mamoe.mirai.console.setting
|
||||
|
||||
import kotlinx.serialization.Decoder
|
||||
import kotlinx.serialization.Encoder
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.SerialDescriptor
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/**
|
||||
* !!! These primitive types are auto-generated by backend/codegen/src/main/kotlin/net.mamoe.mirai.console.ValuesCodegen.kt
|
||||
* !!! These primitive types are auto-generated by backend/codegen/src/main/kotlin/net.mamoe.mirai.console.codegen.ValuesCodegen.kt
|
||||
* !!! for better performance
|
||||
* !!! DO NOT MODIFY THIS FILE MANUALLY
|
||||
*/
|
||||
@ -25,11 +22,23 @@ import kotlin.reflect.KProperty
|
||||
sealed class Value<T : Any> : ReadWriteProperty<Setting, T> {
|
||||
abstract var value: T
|
||||
|
||||
/**
|
||||
* 用于更新 [value] 的序列化器
|
||||
*/
|
||||
abstract val serializer: KSerializer<T>
|
||||
override fun getValue(thisRef: Setting, property: KProperty<*>): T = value
|
||||
override fun setValue(thisRef: Setting, property: KProperty<*>, value: T) {
|
||||
this.value = value
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (other::class != this::class) return false
|
||||
other as Value<*>
|
||||
return other.value == this.value
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = value.hashCode()
|
||||
}
|
||||
|
||||
sealed class PrimitiveValue<T : Any> : Value<T>()
|
||||
@ -103,35 +112,57 @@ abstract class BooleanListValue internal constructor() : ListValue<Boolean>()
|
||||
abstract class CharListValue internal constructor() : ListValue<Char>()
|
||||
abstract class StringListValue internal constructor() : ListValue<String>()
|
||||
|
||||
abstract class SettingListValue<T : Setting> internal constructor() : Value<List<T>>(), List<T>
|
||||
|
||||
sealed class SetValue<E> : Value<Set<E>>(), Iterable<E> {
|
||||
override fun iterator() = this.value.iterator()
|
||||
}
|
||||
|
||||
abstract class IntSetValue internal constructor() : SetValue<Int>()
|
||||
abstract class ShortSetValue internal constructor() : SetValue<Short>()
|
||||
abstract class ByteSetValue internal constructor() : SetValue<Byte>()
|
||||
abstract class LongSetValue internal constructor() : SetValue<Long>()
|
||||
abstract class FloatSetValue internal constructor() : SetValue<Float>()
|
||||
abstract class DoubleSetValue internal constructor() : SetValue<Double>()
|
||||
abstract class BooleanSetValue internal constructor() : SetValue<Boolean>()
|
||||
abstract class CharSetValue internal constructor() : SetValue<Char>()
|
||||
abstract class StringSetValue internal constructor() : SetValue<String>()
|
||||
|
||||
abstract class SettingSetValue<T : Setting> internal constructor() : Value<Set<T>>(), Set<T>
|
||||
|
||||
abstract class SettingValue<T : Setting> internal constructor() : Value<T>()
|
||||
|
||||
internal fun <T : Setting> Setting.valueImpl(default: T): Value<T> {
|
||||
return object : SettingValue<T>() {
|
||||
private var internalValue: T = default
|
||||
override var value: T
|
||||
get() = internalValue
|
||||
set(new) {
|
||||
if (new != internalValue) {
|
||||
internalValue = new
|
||||
onElementChanged(this)
|
||||
}
|
||||
}
|
||||
override val serializer = object : KSerializer<T> {
|
||||
override val descriptor: SerialDescriptor
|
||||
get() = internalValue.updaterSerializer.descriptor
|
||||
abstract class MutableListValue<T : Any> internal constructor() : Value<MutableList<Value<T>>>(), MutableList<T>
|
||||
|
||||
override fun deserialize(decoder: Decoder): T {
|
||||
internalValue.updaterSerializer.deserialize(decoder)
|
||||
return internalValue
|
||||
}
|
||||
abstract class MutableIntListValue internal constructor() : Value<MutableList<Int>>(), MutableList<Int>
|
||||
abstract class MutableShortListValue internal constructor() : Value<MutableList<Short>>(), MutableList<Short>
|
||||
abstract class MutableByteListValue internal constructor() : Value<MutableList<Byte>>(), MutableList<Byte>
|
||||
abstract class MutableLongListValue internal constructor() : Value<MutableList<Long>>(), MutableList<Long>
|
||||
abstract class MutableFloatListValue internal constructor() : Value<MutableList<Float>>(), MutableList<Float>
|
||||
abstract class MutableDoubleListValue internal constructor() : Value<MutableList<Double>>(), MutableList<Double>
|
||||
abstract class MutableBooleanListValue internal constructor() : Value<MutableList<Boolean>>(), MutableList<Boolean>
|
||||
abstract class MutableCharListValue internal constructor() : Value<MutableList<Char>>(), MutableList<Char>
|
||||
abstract class MutableStringListValue internal constructor() : Value<MutableList<String>>(), MutableList<String>
|
||||
|
||||
override fun serialize(encoder: Encoder, value: T) {
|
||||
internalValue.updaterSerializer.serialize(encoder, SettingSerializerMark)
|
||||
}
|
||||
abstract class MutableSettingListValue<T : Setting> internal constructor() : Value<MutableList<T>>(), MutableList<T>
|
||||
|
||||
}.bind(
|
||||
getter = { internalValue },
|
||||
setter = { internalValue = it }
|
||||
)
|
||||
}
|
||||
}
|
||||
abstract class MutableSetValue<T : Any> internal constructor() : Value<MutableSet<Value<T>>>(), MutableSet<T>
|
||||
|
||||
abstract class MutableIntSetValue internal constructor() : Value<MutableSet<Int>>(), MutableSet<Int>
|
||||
abstract class MutableShortSetValue internal constructor() : Value<MutableSet<Short>>(), MutableSet<Short>
|
||||
abstract class MutableByteSetValue internal constructor() : Value<MutableSet<Byte>>(), MutableSet<Byte>
|
||||
abstract class MutableLongSetValue internal constructor() : Value<MutableSet<Long>>(), MutableSet<Long>
|
||||
abstract class MutableFloatSetValue internal constructor() : Value<MutableSet<Float>>(), MutableSet<Float>
|
||||
abstract class MutableDoubleSetValue internal constructor() : Value<MutableSet<Double>>(), MutableSet<Double>
|
||||
abstract class MutableBooleanSetValue internal constructor() : Value<MutableSet<Boolean>>(), MutableSet<Boolean>
|
||||
abstract class MutableCharSetValue internal constructor() : Value<MutableSet<Char>>(), MutableSet<Char>
|
||||
abstract class MutableStringSetValue internal constructor() : Value<MutableSet<String>>(), MutableSet<String>
|
||||
|
||||
abstract class MutableSettingSetValue<T : Setting> internal constructor() : Value<MutableSet<T>>(), MutableSet<T>
|
||||
|
||||
|
||||
/**
|
||||
* 只引用这个对象, 而不跟踪其成员.
|
||||
* 仅适用于基础类型, 用于 mutable list/map 等情况; 或标注了 [Serializable] 的类.
|
||||
*/
|
||||
abstract class DynamicReferenceValue<T : Any> internal constructor() : Value<T>()
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,271 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.setting
|
||||
|
||||
import kotlinx.serialization.ImplicitReflectionSerializer
|
||||
import kotlinx.serialization.serializer
|
||||
import net.mamoe.yamlkt.Yaml
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
internal fun <E, R> MutableList<E>.shadowMap(transform: (E) -> R, transformBack: (R) -> E): MutableList<R> {
|
||||
return object : MutableList<R> {
|
||||
override val size: Int get() = this@shadowMap.size
|
||||
|
||||
override fun contains(element: R): Boolean = this@shadowMap.any { it.let(transform) == element }
|
||||
override fun containsAll(elements: Collection<R>): Boolean = elements.all(::contains)
|
||||
override fun get(index: Int): R = this@shadowMap[index].let(transform)
|
||||
override fun indexOf(element: R): Int = this@shadowMap.indexOfFirst { it.let(transform) == element }
|
||||
override fun isEmpty(): Boolean = this@shadowMap.isEmpty()
|
||||
override fun iterator(): MutableIterator<R> = object : MutableIterator<R> {
|
||||
private val delegate = this@shadowMap.iterator()
|
||||
override fun hasNext(): Boolean = delegate.hasNext()
|
||||
override fun next(): R = delegate.next().let(transform)
|
||||
override fun remove() = delegate.remove()
|
||||
}
|
||||
|
||||
override fun lastIndexOf(element: R): Int = this@shadowMap.indexOfLast { it.let(transform) == element }
|
||||
override fun add(element: R): Boolean = this@shadowMap.add(element.let(transformBack))
|
||||
override fun add(index: Int, element: R) = this@shadowMap.add(index, element.let(transformBack))
|
||||
override fun addAll(index: Int, elements: Collection<R>): Boolean =
|
||||
this@shadowMap.addAll(index, elements.map(transformBack))
|
||||
|
||||
override fun addAll(elements: Collection<R>): Boolean = this@shadowMap.addAll(elements.map(transformBack))
|
||||
override fun clear() = this@shadowMap.clear()
|
||||
|
||||
override fun listIterator(): MutableListIterator<R> = object : MutableListIterator<R> {
|
||||
private val delegate = this@shadowMap.listIterator()
|
||||
override fun hasPrevious(): Boolean = delegate.hasPrevious()
|
||||
override fun nextIndex(): Int = delegate.nextIndex()
|
||||
override fun previous(): R = delegate.previous().let(transform)
|
||||
override fun previousIndex(): Int = delegate.previousIndex()
|
||||
override fun add(element: R) = delegate.add(element.let(transformBack))
|
||||
override fun hasNext(): Boolean = delegate.hasNext()
|
||||
override fun next(): R = delegate.next().let(transform)
|
||||
override fun remove() = delegate.remove()
|
||||
override fun set(element: R) = delegate.set(element.let(transformBack))
|
||||
}
|
||||
|
||||
override fun listIterator(index: Int): MutableListIterator<R> = object : MutableListIterator<R> {
|
||||
private val delegate = this@shadowMap.listIterator(index)
|
||||
override fun hasPrevious(): Boolean = delegate.hasPrevious()
|
||||
override fun nextIndex(): Int = delegate.nextIndex()
|
||||
override fun previous(): R = delegate.previous().let(transform)
|
||||
override fun previousIndex(): Int = delegate.previousIndex()
|
||||
override fun add(element: R) = delegate.add(element.let(transformBack))
|
||||
override fun hasNext(): Boolean = delegate.hasNext()
|
||||
override fun next(): R = delegate.next().let(transform)
|
||||
override fun remove() = delegate.remove()
|
||||
override fun set(element: R) = delegate.set(element.let(transformBack))
|
||||
}
|
||||
|
||||
override fun remove(element: R): Boolean = this@shadowMap.removeIf { it.let(transform) == element }
|
||||
override fun removeAll(elements: Collection<R>): Boolean = elements.all(::remove)
|
||||
override fun removeAt(index: Int): R = this@shadowMap.removeAt(index).let(transform)
|
||||
override fun retainAll(elements: Collection<R>): Boolean = this@shadowMap.retainAll(elements.map(transformBack))
|
||||
override fun set(index: Int, element: R): R =
|
||||
this@shadowMap.set(index, element.let(transformBack)).let(transform)
|
||||
|
||||
override fun subList(fromIndex: Int, toIndex: Int): MutableList<R> =
|
||||
this@shadowMap.subList(fromIndex, toIndex).map(transform).toMutableList()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal fun <E, R> MutableSet<E>.shadowMap(transform: (E) -> R, transformBack: (R) -> E): MutableSet<R> {
|
||||
return object : MutableSet<R> {
|
||||
override val size: Int get() = this@shadowMap.size
|
||||
|
||||
override fun contains(element: R): Boolean = this@shadowMap.any { it.let(transform) == element }
|
||||
override fun containsAll(elements: Collection<R>): Boolean = elements.all(::contains)
|
||||
override fun isEmpty(): Boolean = this@shadowMap.isEmpty()
|
||||
override fun iterator(): MutableIterator<R> = object : MutableIterator<R> {
|
||||
private val delegate = this@shadowMap.iterator()
|
||||
override fun hasNext(): Boolean = delegate.hasNext()
|
||||
override fun next(): R = delegate.next().let(transform)
|
||||
override fun remove() = delegate.remove()
|
||||
}
|
||||
|
||||
override fun add(element: R): Boolean = this@shadowMap.add(element.let(transformBack))
|
||||
override fun addAll(elements: Collection<R>): Boolean = this@shadowMap.addAll(elements.map(transformBack))
|
||||
override fun clear() = this@shadowMap.clear()
|
||||
|
||||
override fun remove(element: R): Boolean = this@shadowMap.removeIf { it.let(transform) == element }
|
||||
override fun removeAll(elements: Collection<R>): Boolean = elements.all(::remove)
|
||||
override fun retainAll(elements: Collection<R>): Boolean = this@shadowMap.retainAll(elements.map(transformBack))
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <T> dynamicList(supplier: () -> List<T>): List<T> {
|
||||
return object : List<T> {
|
||||
override val size: Int get() = supplier().size
|
||||
override fun contains(element: T): Boolean = supplier().contains(element)
|
||||
override fun containsAll(elements: Collection<T>): Boolean = supplier().containsAll(elements)
|
||||
override fun get(index: Int): T = supplier()[index]
|
||||
override fun indexOf(element: T): Int = supplier().indexOf(element)
|
||||
override fun isEmpty(): Boolean = supplier().isEmpty()
|
||||
override fun iterator(): Iterator<T> = supplier().iterator()
|
||||
override fun lastIndexOf(element: T): Int = supplier().lastIndexOf(element)
|
||||
override fun listIterator(): ListIterator<T> = supplier().listIterator()
|
||||
override fun listIterator(index: Int): ListIterator<T> = supplier().listIterator(index)
|
||||
override fun subList(fromIndex: Int, toIndex: Int): List<T> = supplier().subList(fromIndex, toIndex)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <T> dynamicSet(supplier: () -> Set<T>): Set<T> {
|
||||
return object : Set<T> {
|
||||
override val size: Int get() = supplier().size
|
||||
override fun contains(element: T): Boolean = supplier().contains(element)
|
||||
override fun containsAll(elements: Collection<T>): Boolean = supplier().containsAll(elements)
|
||||
override fun isEmpty(): Boolean = supplier().isEmpty()
|
||||
override fun iterator(): Iterator<T> = supplier().iterator()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal fun <T> dynamicMutableList(supplier: () -> MutableList<T>): MutableList<T> {
|
||||
return object : MutableList<T> {
|
||||
override val size: Int get() = supplier().size
|
||||
override fun contains(element: T): Boolean = supplier().contains(element)
|
||||
override fun containsAll(elements: Collection<T>): Boolean = supplier().containsAll(elements)
|
||||
override fun get(index: Int): T = supplier()[index]
|
||||
override fun indexOf(element: T): Int = supplier().indexOf(element)
|
||||
override fun isEmpty(): Boolean = supplier().isEmpty()
|
||||
override fun iterator(): MutableIterator<T> = supplier().iterator()
|
||||
override fun lastIndexOf(element: T): Int = supplier().lastIndexOf(element)
|
||||
override fun add(element: T): Boolean = supplier().add(element)
|
||||
override fun add(index: Int, element: T) = supplier().add(index, element)
|
||||
override fun addAll(index: Int, elements: Collection<T>): Boolean = supplier().addAll(index, elements)
|
||||
override fun addAll(elements: Collection<T>): Boolean = supplier().addAll(elements)
|
||||
override fun clear() = supplier().clear()
|
||||
override fun listIterator(): MutableListIterator<T> = supplier().listIterator()
|
||||
override fun listIterator(index: Int): MutableListIterator<T> = supplier().listIterator(index)
|
||||
override fun remove(element: T): Boolean = supplier().remove(element)
|
||||
override fun removeAll(elements: Collection<T>): Boolean = supplier().removeAll(elements)
|
||||
override fun removeAt(index: Int): T = supplier().removeAt(index)
|
||||
override fun retainAll(elements: Collection<T>): Boolean = supplier().retainAll(elements)
|
||||
override fun set(index: Int, element: T): T = supplier().set(index, element)
|
||||
override fun subList(fromIndex: Int, toIndex: Int): MutableList<T> = supplier().subList(fromIndex, toIndex)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal fun <T> dynamicMutableSet(supplier: () -> MutableSet<T>): MutableSet<T> {
|
||||
return object : MutableSet<T> {
|
||||
override val size: Int get() = supplier().size
|
||||
override fun contains(element: T): Boolean = supplier().contains(element)
|
||||
override fun containsAll(elements: Collection<T>): Boolean = supplier().containsAll(elements)
|
||||
override fun isEmpty(): Boolean = supplier().isEmpty()
|
||||
override fun iterator(): MutableIterator<T> = supplier().iterator()
|
||||
override fun add(element: T): Boolean = supplier().add(element)
|
||||
override fun addAll(elements: Collection<T>): Boolean = supplier().addAll(elements)
|
||||
override fun clear() = supplier().clear()
|
||||
override fun remove(element: T): Boolean = supplier().remove(element)
|
||||
override fun removeAll(elements: Collection<T>): Boolean = supplier().removeAll(elements)
|
||||
override fun retainAll(elements: Collection<T>): Boolean = supplier().retainAll(elements)
|
||||
}
|
||||
}
|
||||
|
||||
internal inline fun <T> MutableList<T>.observable(crossinline onChanged: () -> Unit): MutableList<T> {
|
||||
return object : MutableList<T> {
|
||||
override val size: Int get() = this@observable.size
|
||||
override fun contains(element: T): Boolean = this@observable.contains(element)
|
||||
override fun containsAll(elements: Collection<T>): Boolean = this@observable.containsAll(elements)
|
||||
override fun get(index: Int): T = this@observable[index]
|
||||
override fun indexOf(element: T): Int = this@observable.indexOf(element)
|
||||
override fun isEmpty(): Boolean = this@observable.isEmpty()
|
||||
override fun iterator(): MutableIterator<T> = object : MutableIterator<T> {
|
||||
private val delegate = this@observable.iterator()
|
||||
override fun hasNext(): Boolean = delegate.hasNext()
|
||||
override fun next(): T = delegate.next()
|
||||
override fun remove() = delegate.remove().also { onChanged() }
|
||||
}
|
||||
|
||||
override fun lastIndexOf(element: T): Int = this@observable.lastIndexOf(element)
|
||||
override fun add(element: T): Boolean = this@observable.add(element).also { onChanged() }
|
||||
override fun add(index: Int, element: T) = this@observable.add(index, element).also { onChanged() }
|
||||
override fun addAll(index: Int, elements: Collection<T>): Boolean =
|
||||
this@observable.addAll(index, elements).also { onChanged() }
|
||||
|
||||
override fun addAll(elements: Collection<T>): Boolean = this@observable.addAll(elements).also { onChanged() }
|
||||
override fun clear() = this@observable.clear().also { onChanged() }
|
||||
override fun listIterator(): MutableListIterator<T> = object : MutableListIterator<T> {
|
||||
private val delegate = this@observable.listIterator()
|
||||
override fun hasPrevious(): Boolean = delegate.hasPrevious()
|
||||
override fun nextIndex(): Int = delegate.nextIndex()
|
||||
override fun previous(): T = delegate.previous()
|
||||
override fun previousIndex(): Int = delegate.previousIndex()
|
||||
override fun add(element: T) = delegate.add(element).also { onChanged() }
|
||||
override fun hasNext(): Boolean = delegate.hasNext()
|
||||
override fun next(): T = delegate.next()
|
||||
override fun remove() = delegate.remove().also { onChanged() }
|
||||
override fun set(element: T) = delegate.set(element).also { onChanged() }
|
||||
}
|
||||
|
||||
override fun listIterator(index: Int): MutableListIterator<T> = object : MutableListIterator<T> {
|
||||
private val delegate = this@observable.listIterator(index)
|
||||
override fun hasPrevious(): Boolean = delegate.hasPrevious()
|
||||
override fun nextIndex(): Int = delegate.nextIndex()
|
||||
override fun previous(): T = delegate.previous()
|
||||
override fun previousIndex(): Int = delegate.previousIndex()
|
||||
override fun add(element: T) = delegate.add(element).also { onChanged() }
|
||||
override fun hasNext(): Boolean = delegate.hasNext()
|
||||
override fun next(): T = delegate.next()
|
||||
override fun remove() = delegate.remove().also { onChanged() }
|
||||
override fun set(element: T) = delegate.set(element).also { onChanged() }
|
||||
}
|
||||
|
||||
override fun remove(element: T): Boolean = this@observable.remove(element).also { onChanged() }
|
||||
override fun removeAll(elements: Collection<T>): Boolean =
|
||||
this@observable.removeAll(elements).also { onChanged() }
|
||||
|
||||
override fun removeAt(index: Int): T = this@observable.removeAt(index).also { onChanged() }
|
||||
override fun retainAll(elements: Collection<T>): Boolean =
|
||||
this@observable.retainAll(elements).also { onChanged() }
|
||||
|
||||
override fun set(index: Int, element: T): T = this@observable.set(index, element).also { onChanged() }
|
||||
override fun subList(fromIndex: Int, toIndex: Int): MutableList<T> = this@observable.subList(fromIndex, toIndex)
|
||||
}
|
||||
}
|
||||
|
||||
internal inline fun <T> MutableSet<T>.observable(crossinline onChanged: () -> Unit): MutableSet<T> {
|
||||
return object : MutableSet<T> {
|
||||
override val size: Int get() = this@observable.size
|
||||
override fun contains(element: T): Boolean = this@observable.contains(element)
|
||||
override fun containsAll(elements: Collection<T>): Boolean = this@observable.containsAll(elements)
|
||||
override fun isEmpty(): Boolean = this@observable.isEmpty()
|
||||
override fun iterator(): MutableIterator<T> = object : MutableIterator<T> {
|
||||
private val delegate = this@observable.iterator()
|
||||
override fun hasNext(): Boolean = delegate.hasNext()
|
||||
override fun next(): T = delegate.next()
|
||||
override fun remove() = delegate.remove().also { onChanged() }
|
||||
}
|
||||
|
||||
override fun add(element: T): Boolean = this@observable.add(element).also { onChanged() }
|
||||
override fun addAll(elements: Collection<T>): Boolean = this@observable.addAll(elements).also { onChanged() }
|
||||
override fun clear() = this@observable.clear().also { onChanged() }
|
||||
override fun remove(element: T): Boolean = this@observable.remove(element).also { onChanged() }
|
||||
override fun removeAll(elements: Collection<T>): Boolean =
|
||||
this@observable.removeAll(elements).also { onChanged() }
|
||||
|
||||
override fun retainAll(elements: Collection<T>): Boolean =
|
||||
this@observable.retainAll(elements).also { onChanged() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@OptIn(ImplicitReflectionSerializer::class)
|
||||
internal fun <R : Any> Any.smartCastPrimitive(clazz: KClass<R>): R {
|
||||
kotlin.runCatching {
|
||||
return Yaml.default.parse(clazz.serializer(), this.toString())
|
||||
}.getOrElse {
|
||||
throw IllegalArgumentException("Cannot cast '$this' to ${clazz.qualifiedName}", it)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user