diff --git a/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/SettingValueUseSiteCodegen.kt b/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/SettingValueUseSiteCodegen.kt index 99269419a..00aa5a915 100644 --- a/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/SettingValueUseSiteCodegen.kt +++ b/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/SettingValueUseSiteCodegen.kt @@ -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,10 +67,52 @@ fun genAllValueUseSite(): String = buildString { appendln(genValueUseSite("Array<${number}>", "Typed${number}Array")) } - // PRIMITIVE LISTS - for (number in NUMBERS + OTHER_PRIMITIVES) { - appendln(genValueUseSite("List<${number}>", "${number}List")) + // PRIMITIVE LISTS / PRIMITIVE SETS + for (collectionName in listOf("List", "Set")) { + for (number in NUMBERS + OTHER_PRIMITIVES) { + 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 Setting.value(default: T): Value { + require(this::class != default::class) { + "Recursive nesting is prohibited" + } + return valueImpl(default) + } + + inline fun Setting.value(default: T, crossinline initializer: T.() -> Unit): Value = + value(default).also { it.value.apply(initializer) } + + inline fun Setting.value(default: List): SettingListValue = valueImpl(default) + + @JvmName("valueMutable") + inline fun Setting.value(default: MutableList): MutableSettingListValue = valueImpl(default) + + + inline fun Setting.value(default: Set): SettingSetValue = valueImpl(default) + + @JvmName("valueMutable") + inline fun Setting.value(default: MutableSet): MutableSettingSetValue = valueImpl(default) + """ + ) } fun genValueUseSite(kotlinTypeName: String, miraiValueName: String): String = diff --git a/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/ValueImplCodegen.kt b/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/ValueImplCodegen.kt index 7d40123f1..0401e5093 100644 --- a/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/ValueImplCodegen.kt +++ b/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/ValueImplCodegen.kt @@ -9,6 +9,7 @@ package net.mamoe.mirai.console.codegen +import org.intellij.lang.annotations.Language import java.io.File @@ -44,29 +45,136 @@ 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 - for (number in NUMBERS + OTHER_PRIMITIVES) { - appendln(genValueImpl("List<${number}>", "${number}List", "ListSerializer(${number}.serializer())", false)) + // PRIMITIVE LISTS / SETS + for (collectionName in listOf("List", "Set")) { + for (number in NUMBERS + OTHER_PRIMITIVES) { + 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> = object : KSerializer> { + 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 Setting.valueImpl(default: T): Value { + return object : SettingValue() { + 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{ + 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 = @@ -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" diff --git a/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/ValuesCodegen.kt b/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/ValuesCodegen.kt index 7139245b0..3b3d095c9 100644 --- a/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/ValuesCodegen.kt +++ b/backend/codegen/src/main/kotlin/net/mamoe/mirai/console/codegen/ValuesCodegen.kt @@ -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", @@ -54,10 +55,10 @@ internal val OTHER_PRIMITIVES = listOf( ) fun genPublicApi() = buildString { - fun appendln(@Language("kt") code: String){ + fun appendln(@Language("kt") code: String) { this.appendln(code.trimIndent()) } - + appendln(COPYRIGHT.trim()) appendln() appendln( @@ -86,11 +87,23 @@ fun genPublicApi() = buildString { sealed class Value : ReadWriteProperty { abstract var value: T + /** + * 用于更新 [value] 的序列化器 + */ abstract val serializer: KSerializer 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,64 +189,83 @@ sealed class Value : ReadWriteProperty { appendln() - // TYPED LISTS + // TYPED LISTS / SETS + for (collectionName in listOf("List", "Set")) { - appendln( - """ - sealed class ListValue : Value>(), Iterable{ + appendln( + """ + sealed class ${collectionName}Value : Value<${collectionName}>(), Iterable{ override fun iterator() = this.value.iterator() } """ - ) + ) - for (number in (NUMBERS + OTHER_PRIMITIVES)) { - val template = """ - abstract class ${number}ListValue internal constructor() : ListValue<${number}>() + for (number in (NUMBERS + OTHER_PRIMITIVES)) { + val template = """ + abstract class ${number}${collectionName}Value internal constructor() : ${collectionName}Value<${number}>() """ - appendln(template) + appendln(template) + } + + appendln() + // SETTING + appendln( + """ + abstract class Setting${collectionName}Value internal constructor() : Value<${collectionName}>(), ${collectionName} + """ + ) + appendln() } - appendln() - - // FOR COMPLEX TYPES + // SETTING VALUE appendln( """ abstract class SettingValue internal constructor() : Value() - - internal fun Setting.valueImpl(default: T): Value { - return object : SettingValue() { - 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{ - 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 internal constructor() : Value>>(), Mutable${collectionName} + """ + ) + + appendln() + + for (number in (NUMBERS + OTHER_PRIMITIVES)) { + appendln( + """ + abstract class Mutable${number}${collectionName}Value internal constructor() : Value>(), Mutable${collectionName}<${number}> + """ + ) + } + + appendln() + // SETTING + appendln( + """ + abstract class MutableSetting${collectionName}Value internal constructor() : Value>(), Mutable${collectionName} + """ + ) + appendln() + } + + appendln() + // DYNAMIC + + appendln( + """ + /** + * 只引用这个对象, 而不跟踪其成员. + * 仅适用于基础类型, 用于 mutable list/map 等情况; 或标注了 [Serializable] 的类. + */ + abstract class DynamicReferenceValue internal constructor() : Value() + """ + ) } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Internal.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Internal.kt new file mode 100644 index 000000000..46a7b73ef --- /dev/null +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Internal.kt @@ -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, KProperty<*>>> = mutableListOf() + + @JvmField + internal var built: Boolean = false + + internal val updaterSerializer: KSerializer by lazy { + built = true + SettingUpdaterSerializer(this as Setting) + } + + internal val kotlinSerializer: KSerializer by lazy { + object : KSerializer { + 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 { + 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 + 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, + value.value + ) + } + } + +} + +internal object SettingSerializerMark + +internal val KProperty<*>.serialNameOrPropertyName: String get() = this.findAnnotation()?.value ?: this.name + +internal inline fun KSerializer.bind( + crossinline setter: (E) -> Unit, + crossinline getter: () -> E +): KSerializer { + return object : KSerializer { + 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()) + } +} diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Setting.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Setting.kt index c03ff53e9..ed4373690 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Setting.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/Setting.kt @@ -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 KSerializer.bind( - crossinline setter: (E) -> Unit, - crossinline getter: () -> E -): KSerializer { - return object : KSerializer { - 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()?.value ?: this::class.qualifiedName @@ -56,103 +39,9 @@ abstract class Setting { return this } - @JvmField - internal var valueList: MutableList, KProperty<*>>> = mutableListOf() - private var built: Boolean = false - - internal val updaterSerializer: KSerializer by lazy { - built = true - SettingUpdaterSerializer(this) - } - - internal val kotlinSerializer: KSerializer by lazy { - object : KSerializer { - 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.serializer: KSerializer get() = kotlinSerializer as KSerializer - -internal class SettingUpdaterSerializer( - private val instance: Setting -) : KSerializer { - 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 - ) - } - } 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, - value.value - ) - } - } - -} - -internal object SettingSerializerMark - -internal val KProperty<*>.serialNameOrPropertyName: String get() = this.findAnnotation()?.value ?: this.name - - -fun Setting.value(default: T): Value = valueImpl(default) -inline fun Setting.value(default: T, crossinline initializer: T.() -> Unit): Value = - value(default).also { it.value.apply(initializer) } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/ValueImpl.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/ValueImpl.kt new file mode 100644 index 000000000..0331ad96e --- /dev/null +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/ValueImpl.kt @@ -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 Setting.valueImpl( + default: List +): SettingListValue = valueImpl(default, T::class.createInstance().serializer) + +@PublishedApi +@JvmName("valueImplSettingMutable") +@Suppress("UNCHECKED_CAST") +internal inline fun Setting.valueImpl( + default: MutableList +): MutableSettingListValue = valueImpl(default, T::class.createInstance().serializer) + + +/* +@PublishedApi +@JvmName("valueImpl1") +internal fun Setting.valueImpl( + default: MutableList, + valueMapper: (T) -> Value, + elementSerializer: KSerializer +): MutableListValue = valueImpl(default.mapTo(mutableListOf(), valueMapper), valueMapper, elementSerializer) +*/ +internal fun Setting.valueImpl( + default: MutableList>, + valueMapper: (T) -> Value, + elementSerializer: KSerializer +): MutableListValue { + var internalValue: MutableList> = default + + fun updateShadow(): MutableList = + internalValue.shadowMap(transform = { it.value }, transformBack = { valueMapper(it) }) + + var shadowed: MutableList = updateShadow() + return object : MutableListValue(), MutableList by dynamicMutableList({ shadowed }) { + override var value: MutableList> + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + shadowed = updateShadow() + onElementChanged(this) + } + } + override val serializer: KSerializer>> = object : KSerializer>> { + private val delegate = ListSerializer(elementSerializer) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableList> { + return delegate.deserialize(decoder).mapTo(mutableListOf(), valueMapper) + } + + override fun serialize(encoder: Encoder, value: MutableList>) { + delegate.serialize(encoder, value.map { it.value }) + } + + } + } +} + +@PublishedApi +internal fun Setting.valueImpl( + default: MutableList, + elementSerializer: KSerializer +): MutableSettingListValue { + var internalValue: MutableList = default + + return object : MutableSettingListValue(), MutableList by dynamicMutableList({ internalValue }) { + override var value: MutableList + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = ListSerializer(elementSerializer) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableList { + return delegate.deserialize(decoder).toMutableList() // TODO: 2020/5/17 ATTACH OBSERVER + } + + override fun serialize(encoder: Encoder, value: MutableList) { + delegate.serialize(encoder, value) + } + + } + } +} + +@PublishedApi +internal fun Setting.valueImpl( + default: List, + elementSerializer: KSerializer +): SettingListValue { + var internalValue: List = default + + return object : SettingListValue(), List by dynamicList({ internalValue }) { + override var value: List + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = ListSerializer(elementSerializer) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): List { + return delegate.deserialize(decoder) // TODO: 2020/5/17 ATTACH OBSERVER + } + + override fun serialize(encoder: Encoder, value: List) { + delegate.serialize(encoder, value) + } + + } + } +} + +@PublishedApi +internal fun Setting.valueImpl( + default: Set, + elementSerializer: KSerializer +): SettingSetValue { + var internalValue: Set = default + + return object : SettingSetValue(), Set by dynamicSet({ internalValue }) { + override var value: Set + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = SetSerializer(elementSerializer) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): Set { + return delegate.deserialize(decoder) // TODO: 2020/5/17 ATTACH OBSERVER + } + + override fun serialize(encoder: Encoder, value: Set) { + delegate.serialize(encoder, value) + } + + } + } +} + +@PublishedApi +internal fun Setting.valueImpl( + default: MutableSet, + elementSerializer: KSerializer +): MutableSettingSetValue { + var internalValue: MutableSet = default + + return object : MutableSettingSetValue(), MutableSet by dynamicMutableSet({ internalValue }) { + override var value: MutableSet + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = SetSerializer(elementSerializer) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableSet { + return delegate.deserialize(decoder).toMutableSet() // TODO: 2020/5/17 ATTACH OBSERVER + } + + override fun serialize(encoder: Encoder, value: MutableSet) { + delegate.serialize(encoder, value) + } + + } + } +} + +// endregion + + +// region MUTABLE SET + +@PublishedApi +@JvmName("valueImplSetting") +@Suppress("UNCHECKED_CAST") +internal inline fun Setting.valueImpl( + default: Set +): SettingSetValue = valueImpl(default, T::class.createInstance().serializer) + +@PublishedApi +@JvmName("valueImplSettingMutable") +@Suppress("UNCHECKED_CAST") +internal inline fun Setting.valueImpl( + default: MutableSet +): MutableSettingSetValue = valueImpl(default, T::class.createInstance().serializer) + +/* +@JvmName("valueImpl1") +@PublishedApi +internal fun Setting.valueImpl( + default: MutableSet, + valueMapper: (T) -> Value, + elementSerializer: KSerializer +): MutableSetValue = valueImpl(default.mapTo(mutableSetOf(), valueMapper), valueMapper, elementSerializer) +*/ +@JvmName("valueImplMutable") +internal fun Setting.valueImpl( + default: MutableSet>, + valueMapper: (T) -> Value, + elementSerializer: KSerializer +): MutableSetValue { + var internalValue: MutableSet> = default + + fun updateShadow(): MutableSet = + internalValue.shadowMap(transform = { it.value }, transformBack = { valueMapper(it) }) + + var shadowed: MutableSet = updateShadow() + return object : MutableSetValue(), MutableSet by dynamicMutableSet({ shadowed }) { + override var value: MutableSet> + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + shadowed = updateShadow() + onElementChanged(this) + } + } + override val serializer: KSerializer>> = object : KSerializer>> { + private val delegate = SetSerializer(elementSerializer) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableSet> { + return delegate.deserialize(decoder).mapTo(mutableSetOf(), valueMapper) + } + + override fun serialize(encoder: Encoder, value: MutableSet>) { + delegate.serialize(encoder, value.mapTo(mutableSetOf()) { it.value }) + } + } + } +} + +// endregion + +// region DYNAMIC PRIMITIVES AND SERIALIZABLE + +/** + * For primitives and serializable only + */ +@PublishedApi +internal inline fun Setting.valueImpl(default: T): Value = + valueImpl(default, T::class) + +@PublishedApi +internal fun Setting.valueImpl(default: T, clazz: KClass): Value { + if (default is Setting) @Suppress("UNCHECKED_CAST") return valueImpl(default as Setting) as Value + + @OptIn(ImplicitReflectionSerializer::class) + requireNotNull(clazz.serializerOrNull()) { + "${clazz.qualifiedName} is not serializable" + } + return object : DynamicReferenceValue() { + override var value: T = default + override val serializer: KSerializer + get() = object : KSerializer { + 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 \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/_Setting.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/_Setting.kt index 83dbe7345..2f4b80a48 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/_Setting.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/_Setting.kt @@ -1,4 +1,3 @@ - /* * Copyright 2020 Mamoe Technologies and contributors. * @@ -52,4 +51,88 @@ fun Setting.value(default: List): DoubleListValue = valueImpl(default) fun Setting.value(default: List): BooleanListValue = valueImpl(default) fun Setting.value(default: List): CharListValue = valueImpl(default) fun Setting.value(default: List): StringListValue = valueImpl(default) +fun Setting.value(default: Set): IntSetValue = valueImpl(default) +fun Setting.value(default: Set): ShortSetValue = valueImpl(default) +fun Setting.value(default: Set): ByteSetValue = valueImpl(default) +fun Setting.value(default: Set): LongSetValue = valueImpl(default) +fun Setting.value(default: Set): FloatSetValue = valueImpl(default) +fun Setting.value(default: Set): DoubleSetValue = valueImpl(default) +fun Setting.value(default: Set): BooleanSetValue = valueImpl(default) +fun Setting.value(default: Set): CharSetValue = valueImpl(default) +fun Setting.value(default: Set): StringSetValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableList): MutableIntListValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableList): MutableShortListValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableList): MutableByteListValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableList): MutableLongListValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableList): MutableFloatListValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableList): MutableDoubleListValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableList): MutableBooleanListValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableList): MutableCharListValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableList): MutableStringListValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableSet): MutableIntSetValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableSet): MutableShortSetValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableSet): MutableByteSetValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableSet): MutableLongSetValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableSet): MutableFloatSetValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableSet): MutableDoubleSetValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableSet): MutableBooleanSetValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableSet): MutableCharSetValue = valueImpl(default) + +@JvmName("valueMutable") +fun Setting.value(default: MutableSet): MutableStringSetValue = valueImpl(default) + +fun Setting.value(default: T): Value { + require(this::class != default::class) { + "Recursive nesting is prohibited" + } + return valueImpl(default) +} + +inline fun Setting.value(default: T, crossinline initializer: T.() -> Unit): Value = + value(default).also { it.value.apply(initializer) } + +inline fun Setting.value(default: List): SettingListValue = valueImpl(default) + +@JvmName("valueMutable") +inline fun Setting.value(default: MutableList): MutableSettingListValue = valueImpl(default) + + +inline fun Setting.value(default: Set): SettingSetValue = valueImpl(default) + +@JvmName("valueMutable") +inline fun Setting.value(default: MutableSet): MutableSettingSetValue = valueImpl(default) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/_Value.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/_Value.kt index 1ffe99de5..1aa6600b5 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/_Value.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/_Value.kt @@ -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 : ReadWriteProperty { abstract var value: T + /** + * 用于更新 [value] 的序列化器 + */ abstract val serializer: KSerializer 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 : Value() @@ -75,7 +84,7 @@ abstract class CharArrayValue internal constructor() : PrimitiveArrayValue = this.value.iterator() } -sealed class TypedPrimitiveArrayValue : ArrayValue>() , Iterable{ +sealed class TypedPrimitiveArrayValue : ArrayValue>(), Iterable { override fun iterator() = this.value.iterator() } @@ -89,7 +98,7 @@ abstract class TypedBooleanArrayValue internal constructor() : TypedPrimitiveArr abstract class TypedCharArrayValue internal constructor() : TypedPrimitiveArrayValue() abstract class TypedStringArrayValue internal constructor() : TypedPrimitiveArrayValue() -sealed class ListValue : Value>(), Iterable{ +sealed class ListValue : Value>(), Iterable { override fun iterator() = this.value.iterator() } @@ -103,35 +112,57 @@ abstract class BooleanListValue internal constructor() : ListValue() abstract class CharListValue internal constructor() : ListValue() abstract class StringListValue internal constructor() : ListValue() +abstract class SettingListValue internal constructor() : Value>(), List + +sealed class SetValue : Value>(), Iterable { + override fun iterator() = this.value.iterator() +} + +abstract class IntSetValue internal constructor() : SetValue() +abstract class ShortSetValue internal constructor() : SetValue() +abstract class ByteSetValue internal constructor() : SetValue() +abstract class LongSetValue internal constructor() : SetValue() +abstract class FloatSetValue internal constructor() : SetValue() +abstract class DoubleSetValue internal constructor() : SetValue() +abstract class BooleanSetValue internal constructor() : SetValue() +abstract class CharSetValue internal constructor() : SetValue() +abstract class StringSetValue internal constructor() : SetValue() + +abstract class SettingSetValue internal constructor() : Value>(), Set + abstract class SettingValue internal constructor() : Value() -internal fun Setting.valueImpl(default: T): Value { - return object : SettingValue() { - 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 { - override val descriptor: SerialDescriptor - get() = internalValue.updaterSerializer.descriptor +abstract class MutableListValue internal constructor() : Value>>(), MutableList - override fun deserialize(decoder: Decoder): T { - internalValue.updaterSerializer.deserialize(decoder) - return internalValue - } +abstract class MutableIntListValue internal constructor() : Value>(), MutableList +abstract class MutableShortListValue internal constructor() : Value>(), MutableList +abstract class MutableByteListValue internal constructor() : Value>(), MutableList +abstract class MutableLongListValue internal constructor() : Value>(), MutableList +abstract class MutableFloatListValue internal constructor() : Value>(), MutableList +abstract class MutableDoubleListValue internal constructor() : Value>(), MutableList +abstract class MutableBooleanListValue internal constructor() : Value>(), MutableList +abstract class MutableCharListValue internal constructor() : Value>(), MutableList +abstract class MutableStringListValue internal constructor() : Value>(), MutableList - override fun serialize(encoder: Encoder, value: T) { - internalValue.updaterSerializer.serialize(encoder, SettingSerializerMark) - } +abstract class MutableSettingListValue internal constructor() : Value>(), MutableList - }.bind( - getter = { internalValue }, - setter = { internalValue = it } - ) - } -} \ No newline at end of file +abstract class MutableSetValue internal constructor() : Value>>(), MutableSet + +abstract class MutableIntSetValue internal constructor() : Value>(), MutableSet +abstract class MutableShortSetValue internal constructor() : Value>(), MutableSet +abstract class MutableByteSetValue internal constructor() : Value>(), MutableSet +abstract class MutableLongSetValue internal constructor() : Value>(), MutableSet +abstract class MutableFloatSetValue internal constructor() : Value>(), MutableSet +abstract class MutableDoubleSetValue internal constructor() : Value>(), MutableSet +abstract class MutableBooleanSetValue internal constructor() : Value>(), MutableSet +abstract class MutableCharSetValue internal constructor() : Value>(), MutableSet +abstract class MutableStringSetValue internal constructor() : Value>(), MutableSet + +abstract class MutableSettingSetValue internal constructor() : Value>(), MutableSet + + +/** + * 只引用这个对象, 而不跟踪其成员. + * 仅适用于基础类型, 用于 mutable list/map 等情况; 或标注了 [Serializable] 的类. + */ +abstract class DynamicReferenceValue internal constructor() : Value() diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/_ValueImpl.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/_ValueImpl.kt index cc8b445aa..17ce4184b 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/_ValueImpl.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/_ValueImpl.kt @@ -10,11 +10,15 @@ package net.mamoe.mirai.console.setting +import kotlinx.serialization.Decoder +import kotlinx.serialization.Encoder +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerialDescriptor import kotlinx.serialization.builtins.* /** - * !!! This file is auto-generated by test/kotlin/net.mamoe.mirai.console.SettingsCodegen.kt + * !!! This file is auto-generated by backend/codegen/src/kotlin/net.mamoe.mirai.console.codegen.ValueImplCodegen.kt * !!! DO NOT MODIFY THIS FILE MANUALLY */ @@ -30,10 +34,7 @@ internal fun Setting.valueImpl(default: Int): IntValue { onElementChanged(this) } } - override val serializer = Int.serializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = Int.serializer() } } @@ -48,10 +49,7 @@ internal fun Setting.valueImpl(default: Short): ShortValue { onElementChanged(this) } } - override val serializer = Short.serializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = Short.serializer() } } @@ -66,10 +64,7 @@ internal fun Setting.valueImpl(default: Byte): ByteValue { onElementChanged(this) } } - override val serializer = Byte.serializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = Byte.serializer() } } @@ -84,10 +79,7 @@ internal fun Setting.valueImpl(default: Long): LongValue { onElementChanged(this) } } - override val serializer = Long.serializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = Long.serializer() } } @@ -102,10 +94,7 @@ internal fun Setting.valueImpl(default: Float): FloatValue { onElementChanged(this) } } - override val serializer = Float.serializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = Float.serializer() } } @@ -120,10 +109,7 @@ internal fun Setting.valueImpl(default: Double): DoubleValue { onElementChanged(this) } } - override val serializer = Double.serializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = Double.serializer() } } @@ -138,10 +124,7 @@ internal fun Setting.valueImpl(default: Boolean): BooleanValue { onElementChanged(this) } } - override val serializer = Boolean.serializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = Boolean.serializer() } } @@ -156,10 +139,7 @@ internal fun Setting.valueImpl(default: Char): CharValue { onElementChanged(this) } } - override val serializer = Char.serializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = Char.serializer() } } @@ -174,10 +154,7 @@ internal fun Setting.valueImpl(default: String): StringValue { onElementChanged(this) } } - override val serializer = String.serializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = String.serializer() } } @@ -192,10 +169,7 @@ internal fun Setting.valueImpl(default: IntArray): IntArrayValue { onElementChanged(this) } } - override val serializer = IntArraySerializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = IntArraySerializer() } } @@ -210,10 +184,7 @@ internal fun Setting.valueImpl(default: ShortArray): ShortArrayValue { onElementChanged(this) } } - override val serializer = ShortArraySerializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ShortArraySerializer() } } @@ -228,10 +199,7 @@ internal fun Setting.valueImpl(default: ByteArray): ByteArrayValue { onElementChanged(this) } } - override val serializer = ByteArraySerializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ByteArraySerializer() } } @@ -246,10 +214,7 @@ internal fun Setting.valueImpl(default: LongArray): LongArrayValue { onElementChanged(this) } } - override val serializer = LongArraySerializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = LongArraySerializer() } } @@ -264,10 +229,7 @@ internal fun Setting.valueImpl(default: FloatArray): FloatArrayValue { onElementChanged(this) } } - override val serializer = FloatArraySerializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = FloatArraySerializer() } } @@ -282,10 +244,7 @@ internal fun Setting.valueImpl(default: DoubleArray): DoubleArrayValue { onElementChanged(this) } } - override val serializer = DoubleArraySerializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = DoubleArraySerializer() } } @@ -300,10 +259,7 @@ internal fun Setting.valueImpl(default: BooleanArray): BooleanArrayValue { onElementChanged(this) } } - override val serializer = BooleanArraySerializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = BooleanArraySerializer() } } @@ -318,10 +274,7 @@ internal fun Setting.valueImpl(default: CharArray): CharArrayValue { onElementChanged(this) } } - override val serializer = CharArraySerializer().bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = CharArraySerializer() } } @@ -336,10 +289,7 @@ internal fun Setting.valueImpl(default: Array): TypedIntArrayValue { onElementChanged(this) } } - override val serializer = ArraySerializer(Int.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ArraySerializer(Int.serializer()) } } @@ -354,10 +304,7 @@ internal fun Setting.valueImpl(default: Array): TypedShortArrayValue { onElementChanged(this) } } - override val serializer = ArraySerializer(Short.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ArraySerializer(Short.serializer()) } } @@ -372,10 +319,7 @@ internal fun Setting.valueImpl(default: Array): TypedByteArrayValue { onElementChanged(this) } } - override val serializer = ArraySerializer(Byte.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ArraySerializer(Byte.serializer()) } } @@ -390,10 +334,7 @@ internal fun Setting.valueImpl(default: Array): TypedLongArrayValue { onElementChanged(this) } } - override val serializer = ArraySerializer(Long.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ArraySerializer(Long.serializer()) } } @@ -408,10 +349,7 @@ internal fun Setting.valueImpl(default: Array): TypedFloatArrayValue { onElementChanged(this) } } - override val serializer = ArraySerializer(Float.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ArraySerializer(Float.serializer()) } } @@ -426,10 +364,7 @@ internal fun Setting.valueImpl(default: Array): TypedDoubleArrayValue { onElementChanged(this) } } - override val serializer = ArraySerializer(Double.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ArraySerializer(Double.serializer()) } } @@ -444,10 +379,7 @@ internal fun Setting.valueImpl(default: Array): TypedBooleanArrayValue onElementChanged(this) } } - override val serializer = ArraySerializer(Boolean.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ArraySerializer(Boolean.serializer()) } } @@ -462,10 +394,7 @@ internal fun Setting.valueImpl(default: Array): TypedCharArrayValue { onElementChanged(this) } } - override val serializer = ArraySerializer(Char.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ArraySerializer(Char.serializer()) } } @@ -480,10 +409,7 @@ internal fun Setting.valueImpl(default: Array): TypedStringArrayValue { onElementChanged(this) } } - override val serializer = ArraySerializer(String.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ArraySerializer(String.serializer()) } } @@ -498,10 +424,7 @@ internal fun Setting.valueImpl(default: List): IntListValue { onElementChanged(this) } } - override val serializer = ListSerializer(Int.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ListSerializer(Int.serializer()) } } @@ -516,10 +439,7 @@ internal fun Setting.valueImpl(default: List): ShortListValue { onElementChanged(this) } } - override val serializer = ListSerializer(Short.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ListSerializer(Short.serializer()) } } @@ -534,10 +454,7 @@ internal fun Setting.valueImpl(default: List): ByteListValue { onElementChanged(this) } } - override val serializer = ListSerializer(Byte.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ListSerializer(Byte.serializer()) } } @@ -552,10 +469,7 @@ internal fun Setting.valueImpl(default: List): LongListValue { onElementChanged(this) } } - override val serializer = ListSerializer(Long.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ListSerializer(Long.serializer()) } } @@ -570,10 +484,7 @@ internal fun Setting.valueImpl(default: List): FloatListValue { onElementChanged(this) } } - override val serializer = ListSerializer(Float.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ListSerializer(Float.serializer()) } } @@ -588,10 +499,7 @@ internal fun Setting.valueImpl(default: List): DoubleListValue { onElementChanged(this) } } - override val serializer = ListSerializer(Double.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ListSerializer(Double.serializer()) } } @@ -606,10 +514,7 @@ internal fun Setting.valueImpl(default: List): BooleanListValue { onElementChanged(this) } } - override val serializer = ListSerializer(Boolean.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ListSerializer(Boolean.serializer()) } } @@ -624,10 +529,7 @@ internal fun Setting.valueImpl(default: List): CharListValue { onElementChanged(this) } } - override val serializer = ListSerializer(Char.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ListSerializer(Char.serializer()) } } @@ -642,11 +544,801 @@ internal fun Setting.valueImpl(default: List): StringListValue { onElementChanged(this) } } - override val serializer = ListSerializer(String.serializer()).bind( - getter = { internalValue }, - setter = { internalValue = it } - ) + override val serializer = ListSerializer(String.serializer()) + } +} + +internal fun Setting.valueImpl(default: Set): IntSetValue { + return object : IntSetValue() { + private var internalValue: Set = default + override var value: Set + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + override val serializer = SetSerializer(Int.serializer()) + } +} + +internal fun Setting.valueImpl(default: Set): ShortSetValue { + return object : ShortSetValue() { + private var internalValue: Set = default + override var value: Set + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + override val serializer = SetSerializer(Short.serializer()) + } +} + +internal fun Setting.valueImpl(default: Set): ByteSetValue { + return object : ByteSetValue() { + private var internalValue: Set = default + override var value: Set + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + override val serializer = SetSerializer(Byte.serializer()) + } +} + +internal fun Setting.valueImpl(default: Set): LongSetValue { + return object : LongSetValue() { + private var internalValue: Set = default + override var value: Set + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + override val serializer = SetSerializer(Long.serializer()) + } +} + +internal fun Setting.valueImpl(default: Set): FloatSetValue { + return object : FloatSetValue() { + private var internalValue: Set = default + override var value: Set + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + override val serializer = SetSerializer(Float.serializer()) + } +} + +internal fun Setting.valueImpl(default: Set): DoubleSetValue { + return object : DoubleSetValue() { + private var internalValue: Set = default + override var value: Set + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + override val serializer = SetSerializer(Double.serializer()) + } +} + +internal fun Setting.valueImpl(default: Set): BooleanSetValue { + return object : BooleanSetValue() { + private var internalValue: Set = default + override var value: Set + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + override val serializer = SetSerializer(Boolean.serializer()) + } +} + +internal fun Setting.valueImpl(default: Set): CharSetValue { + return object : CharSetValue() { + private var internalValue: Set = default + override var value: Set + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + override val serializer = SetSerializer(Char.serializer()) + } +} + +internal fun Setting.valueImpl(default: Set): StringSetValue { + return object : StringSetValue() { + private var internalValue: Set = default + override var value: Set + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + override val serializer = SetSerializer(String.serializer()) } } +@JvmName("valueImplMutableIntList") +internal fun Setting.valueImpl( + default: MutableList +): MutableIntListValue { + var internalValue: MutableList = default + + return object : MutableIntListValue(), MutableList by dynamicMutableList({ internalValue }) { + override var value: MutableList + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = ListSerializer(Int.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableList { + return delegate.deserialize(decoder).toMutableList().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableList) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableShortList") +internal fun Setting.valueImpl( + default: MutableList +): MutableShortListValue { + var internalValue: MutableList = default + + return object : MutableShortListValue(), MutableList by dynamicMutableList({ internalValue }) { + override var value: MutableList + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = ListSerializer(Short.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableList { + return delegate.deserialize(decoder).toMutableList().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableList) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableByteList") +internal fun Setting.valueImpl( + default: MutableList +): MutableByteListValue { + var internalValue: MutableList = default + + return object : MutableByteListValue(), MutableList by dynamicMutableList({ internalValue }) { + override var value: MutableList + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = ListSerializer(Byte.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableList { + return delegate.deserialize(decoder).toMutableList().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableList) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableLongList") +internal fun Setting.valueImpl( + default: MutableList +): MutableLongListValue { + var internalValue: MutableList = default + + return object : MutableLongListValue(), MutableList by dynamicMutableList({ internalValue }) { + override var value: MutableList + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = ListSerializer(Long.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableList { + return delegate.deserialize(decoder).toMutableList().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableList) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableFloatList") +internal fun Setting.valueImpl( + default: MutableList +): MutableFloatListValue { + var internalValue: MutableList = default + + return object : MutableFloatListValue(), MutableList by dynamicMutableList({ internalValue }) { + override var value: MutableList + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = ListSerializer(Float.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableList { + return delegate.deserialize(decoder).toMutableList().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableList) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableDoubleList") +internal fun Setting.valueImpl( + default: MutableList +): MutableDoubleListValue { + var internalValue: MutableList = default + + return object : MutableDoubleListValue(), MutableList by dynamicMutableList({ internalValue }) { + override var value: MutableList + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = ListSerializer(Double.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableList { + return delegate.deserialize(decoder).toMutableList().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableList) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableBooleanList") +internal fun Setting.valueImpl( + default: MutableList +): MutableBooleanListValue { + var internalValue: MutableList = default + + return object : MutableBooleanListValue(), MutableList by dynamicMutableList({ internalValue }) { + override var value: MutableList + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = ListSerializer(Boolean.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableList { + return delegate.deserialize(decoder).toMutableList().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableList) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableCharList") +internal fun Setting.valueImpl( + default: MutableList +): MutableCharListValue { + var internalValue: MutableList = default + + return object : MutableCharListValue(), MutableList by dynamicMutableList({ internalValue }) { + override var value: MutableList + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = ListSerializer(Char.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableList { + return delegate.deserialize(decoder).toMutableList().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableList) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableStringList") +internal fun Setting.valueImpl( + default: MutableList +): MutableStringListValue { + var internalValue: MutableList = default + + return object : MutableStringListValue(), MutableList by dynamicMutableList({ internalValue }) { + override var value: MutableList + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = ListSerializer(String.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableList { + return delegate.deserialize(decoder).toMutableList().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableList) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableIntSet") +internal fun Setting.valueImpl( + default: MutableSet +): MutableIntSetValue { + var internalValue: MutableSet = default + + return object : MutableIntSetValue(), MutableSet by dynamicMutableSet({ internalValue }) { + override var value: MutableSet + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = SetSerializer(Int.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableSet { + return delegate.deserialize(decoder).toMutableSet().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableSet) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableShortSet") +internal fun Setting.valueImpl( + default: MutableSet +): MutableShortSetValue { + var internalValue: MutableSet = default + + return object : MutableShortSetValue(), MutableSet by dynamicMutableSet({ internalValue }) { + override var value: MutableSet + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = SetSerializer(Short.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableSet { + return delegate.deserialize(decoder).toMutableSet().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableSet) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableByteSet") +internal fun Setting.valueImpl( + default: MutableSet +): MutableByteSetValue { + var internalValue: MutableSet = default + + return object : MutableByteSetValue(), MutableSet by dynamicMutableSet({ internalValue }) { + override var value: MutableSet + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = SetSerializer(Byte.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableSet { + return delegate.deserialize(decoder).toMutableSet().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableSet) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableLongSet") +internal fun Setting.valueImpl( + default: MutableSet +): MutableLongSetValue { + var internalValue: MutableSet = default + + return object : MutableLongSetValue(), MutableSet by dynamicMutableSet({ internalValue }) { + override var value: MutableSet + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = SetSerializer(Long.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableSet { + return delegate.deserialize(decoder).toMutableSet().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableSet) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableFloatSet") +internal fun Setting.valueImpl( + default: MutableSet +): MutableFloatSetValue { + var internalValue: MutableSet = default + + return object : MutableFloatSetValue(), MutableSet by dynamicMutableSet({ internalValue }) { + override var value: MutableSet + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = SetSerializer(Float.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableSet { + return delegate.deserialize(decoder).toMutableSet().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableSet) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableDoubleSet") +internal fun Setting.valueImpl( + default: MutableSet +): MutableDoubleSetValue { + var internalValue: MutableSet = default + + return object : MutableDoubleSetValue(), MutableSet by dynamicMutableSet({ internalValue }) { + override var value: MutableSet + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = SetSerializer(Double.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableSet { + return delegate.deserialize(decoder).toMutableSet().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableSet) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableBooleanSet") +internal fun Setting.valueImpl( + default: MutableSet +): MutableBooleanSetValue { + var internalValue: MutableSet = default + + return object : MutableBooleanSetValue(), MutableSet by dynamicMutableSet({ internalValue }) { + override var value: MutableSet + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = SetSerializer(Boolean.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableSet { + return delegate.deserialize(decoder).toMutableSet().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableSet) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableCharSet") +internal fun Setting.valueImpl( + default: MutableSet +): MutableCharSetValue { + var internalValue: MutableSet = default + + return object : MutableCharSetValue(), MutableSet by dynamicMutableSet({ internalValue }) { + override var value: MutableSet + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = SetSerializer(Char.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableSet { + return delegate.deserialize(decoder).toMutableSet().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableSet) { + delegate.serialize(encoder, value) + } + } + } +} + +@JvmName("valueImplMutableStringSet") +internal fun Setting.valueImpl( + default: MutableSet +): MutableStringSetValue { + var internalValue: MutableSet = default + + return object : MutableStringSetValue(), MutableSet by dynamicMutableSet({ internalValue }) { + override var value: MutableSet + get() = internalValue + set(new) { + if (new != internalValue) { + internalValue = new + onElementChanged(this) + } + } + + private inline val `this` get() = this + + override val serializer: KSerializer> = object : KSerializer> { + private val delegate = SetSerializer(String.serializer()) + override val descriptor: SerialDescriptor = delegate.descriptor + + override fun deserialize(decoder: Decoder): MutableSet { + return delegate.deserialize(decoder).toMutableSet().observable { + onElementChanged(`this`) + } + } + + override fun serialize(encoder: Encoder, value: MutableSet) { + delegate.serialize(encoder, value) + } + } + } +} + + +internal fun Setting.valueImpl(default: T): Value { + return object : SettingValue() { + 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 { + 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) + } + } + } +} + diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/utils.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/utils.kt new file mode 100644 index 000000000..0f069db89 --- /dev/null +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/utils.kt @@ -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 MutableList.shadowMap(transform: (E) -> R, transformBack: (R) -> E): MutableList { + return object : MutableList { + 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): 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 = object : MutableIterator { + 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): Boolean = + this@shadowMap.addAll(index, elements.map(transformBack)) + + override fun addAll(elements: Collection): Boolean = this@shadowMap.addAll(elements.map(transformBack)) + override fun clear() = this@shadowMap.clear() + + override fun listIterator(): MutableListIterator = object : MutableListIterator { + 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 = object : MutableListIterator { + 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): Boolean = elements.all(::remove) + override fun removeAt(index: Int): R = this@shadowMap.removeAt(index).let(transform) + override fun retainAll(elements: Collection): 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 = + this@shadowMap.subList(fromIndex, toIndex).map(transform).toMutableList() + } +} + + +internal fun MutableSet.shadowMap(transform: (E) -> R, transformBack: (R) -> E): MutableSet { + return object : MutableSet { + 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): Boolean = elements.all(::contains) + override fun isEmpty(): Boolean = this@shadowMap.isEmpty() + override fun iterator(): MutableIterator = object : MutableIterator { + 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): 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): Boolean = elements.all(::remove) + override fun retainAll(elements: Collection): Boolean = this@shadowMap.retainAll(elements.map(transformBack)) + } +} + +internal fun dynamicList(supplier: () -> List): List { + return object : List { + override val size: Int get() = supplier().size + override fun contains(element: T): Boolean = supplier().contains(element) + override fun containsAll(elements: Collection): 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 = supplier().iterator() + override fun lastIndexOf(element: T): Int = supplier().lastIndexOf(element) + override fun listIterator(): ListIterator = supplier().listIterator() + override fun listIterator(index: Int): ListIterator = supplier().listIterator(index) + override fun subList(fromIndex: Int, toIndex: Int): List = supplier().subList(fromIndex, toIndex) + } +} + +internal fun dynamicSet(supplier: () -> Set): Set { + return object : Set { + override val size: Int get() = supplier().size + override fun contains(element: T): Boolean = supplier().contains(element) + override fun containsAll(elements: Collection): Boolean = supplier().containsAll(elements) + override fun isEmpty(): Boolean = supplier().isEmpty() + override fun iterator(): Iterator = supplier().iterator() + } +} + + +internal fun dynamicMutableList(supplier: () -> MutableList): MutableList { + return object : MutableList { + override val size: Int get() = supplier().size + override fun contains(element: T): Boolean = supplier().contains(element) + override fun containsAll(elements: Collection): 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 = 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): Boolean = supplier().addAll(index, elements) + override fun addAll(elements: Collection): Boolean = supplier().addAll(elements) + override fun clear() = supplier().clear() + override fun listIterator(): MutableListIterator = supplier().listIterator() + override fun listIterator(index: Int): MutableListIterator = supplier().listIterator(index) + override fun remove(element: T): Boolean = supplier().remove(element) + override fun removeAll(elements: Collection): Boolean = supplier().removeAll(elements) + override fun removeAt(index: Int): T = supplier().removeAt(index) + override fun retainAll(elements: Collection): Boolean = supplier().retainAll(elements) + override fun set(index: Int, element: T): T = supplier().set(index, element) + override fun subList(fromIndex: Int, toIndex: Int): MutableList = supplier().subList(fromIndex, toIndex) + } +} + + +internal fun dynamicMutableSet(supplier: () -> MutableSet): MutableSet { + return object : MutableSet { + override val size: Int get() = supplier().size + override fun contains(element: T): Boolean = supplier().contains(element) + override fun containsAll(elements: Collection): Boolean = supplier().containsAll(elements) + override fun isEmpty(): Boolean = supplier().isEmpty() + override fun iterator(): MutableIterator = supplier().iterator() + override fun add(element: T): Boolean = supplier().add(element) + override fun addAll(elements: Collection): Boolean = supplier().addAll(elements) + override fun clear() = supplier().clear() + override fun remove(element: T): Boolean = supplier().remove(element) + override fun removeAll(elements: Collection): Boolean = supplier().removeAll(elements) + override fun retainAll(elements: Collection): Boolean = supplier().retainAll(elements) + } +} + +internal inline fun MutableList.observable(crossinline onChanged: () -> Unit): MutableList { + return object : MutableList { + override val size: Int get() = this@observable.size + override fun contains(element: T): Boolean = this@observable.contains(element) + override fun containsAll(elements: Collection): 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 = object : MutableIterator { + 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): Boolean = + this@observable.addAll(index, elements).also { onChanged() } + + override fun addAll(elements: Collection): Boolean = this@observable.addAll(elements).also { onChanged() } + override fun clear() = this@observable.clear().also { onChanged() } + override fun listIterator(): MutableListIterator = object : MutableListIterator { + 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 = object : MutableListIterator { + 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): Boolean = + this@observable.removeAll(elements).also { onChanged() } + + override fun removeAt(index: Int): T = this@observable.removeAt(index).also { onChanged() } + override fun retainAll(elements: Collection): 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 = this@observable.subList(fromIndex, toIndex) + } +} + +internal inline fun MutableSet.observable(crossinline onChanged: () -> Unit): MutableSet { + return object : MutableSet { + override val size: Int get() = this@observable.size + override fun contains(element: T): Boolean = this@observable.contains(element) + override fun containsAll(elements: Collection): Boolean = this@observable.containsAll(elements) + override fun isEmpty(): Boolean = this@observable.isEmpty() + override fun iterator(): MutableIterator = object : MutableIterator { + 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): 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): Boolean = + this@observable.removeAll(elements).also { onChanged() } + + override fun retainAll(elements: Collection): Boolean = + this@observable.retainAll(elements).also { onChanged() } + } +} + + +@OptIn(ImplicitReflectionSerializer::class) +internal fun Any.smartCastPrimitive(clazz: KClass): R { + kotlin.runCatching { + return Yaml.default.parse(clazz.serializer(), this.toString()) + }.getOrElse { + throw IllegalArgumentException("Cannot cast '$this' to ${clazz.qualifiedName}", it) + } +} +