mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-13 14:50:43 +08:00
Introduce AbstractValueImpl as superclass to all ValueImpl;
Implement CompositeSetValueImpl, CompositeMapValueImpl, CompositeListValueImpl; Implement value patching and reference tracking; Add SettingTest.kt; Implement SettingImpl.updaterSerializer; `Setting.valueReified` and `Setting.valueFromKType` supports All primitives, Collections and Maps now.
This commit is contained in:
parent
70b9b012e1
commit
9a91c9b2a7
@ -22,9 +22,7 @@ object ValueSettingCodegen {
|
||||
object PrimitiveValuesCodegen : RegionCodegen("Value.kt"), DefaultInvoke {
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) = super.startIndependent()
|
||||
|
||||
override val defaultInvokeArgs: List<KtType>
|
||||
get() = KtPrimitives + KtString
|
||||
override val defaultInvokeArgs: List<KtType> = KtPrimitives + KtString
|
||||
|
||||
override fun StringBuilder.apply(ktType: KtType) {
|
||||
@Suppress("ClassName")
|
||||
@ -42,7 +40,6 @@ object ValueSettingCodegen {
|
||||
object BuiltInSerializerConstantsPrimitivesCodegen : RegionCodegen("_Setting.value.kt"), DefaultInvoke {
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) = super.startIndependent()
|
||||
|
||||
override val defaultInvokeArgs: List<KtType> = KtPrimitives + KtString
|
||||
|
||||
override fun StringBuilder.apply(ktType: KtType) {
|
||||
@ -60,14 +57,12 @@ object ValueSettingCodegen {
|
||||
object PrimitiveValuesImplCodegen : RegionCodegen("_PrimitiveValueDeclarations.kt"), DefaultInvoke {
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) = super.startIndependent()
|
||||
|
||||
override val defaultInvokeArgs: List<KtType>
|
||||
get() = KtPrimitives + KtString
|
||||
override val defaultInvokeArgs: List<KtType> = KtPrimitives + KtString
|
||||
|
||||
override fun StringBuilder.apply(ktType: KtType) {
|
||||
appendKCode(
|
||||
"""
|
||||
internal abstract class ${ktType.standardName}ValueImpl : ${ktType.standardName}Value, SerializerAwareValue<${ktType.standardName}>, KSerializer<Unit> {
|
||||
internal abstract class ${ktType.standardName}ValueImpl : ${ktType.standardName}Value, SerializerAwareValue<${ktType.standardName}>, KSerializer<Unit>, AbstractValueImpl<${ktType.standardName}> {
|
||||
constructor()
|
||||
constructor(default: ${ktType.standardName}) {
|
||||
_value = default
|
||||
@ -89,8 +84,13 @@ internal abstract class ${ktType.standardName}ValueImpl : ${ktType.standardName}
|
||||
final override val serializer: KSerializer<Unit> get() = this
|
||||
final override val descriptor: SerialDescriptor get() = BuiltInSerializerConstants.${ktType.standardName}SerializerDescriptor
|
||||
final override fun serialize(encoder: Encoder, value: Unit) = ${ktType.standardName}.serializer().serialize(encoder, this.value)
|
||||
final override fun deserialize(decoder: Decoder) {
|
||||
value = ${ktType.standardName}.serializer().deserialize(decoder)
|
||||
final override fun deserialize(decoder: Decoder) = setValueBySerializer(${ktType.standardName}.serializer().deserialize(decoder))
|
||||
override fun toString(): String = _value${if (ktType != KtString) "?.toString()" else ""} ?: "${ktType.standardName}Value.value not yet initialized."
|
||||
override fun equals(other: Any?): Boolean = other is ${ktType.standardName}ValueImpl && other::class.java == this::class.java && other._value == this._value
|
||||
override fun hashCode(): Int {
|
||||
val value = _value
|
||||
return if (value == null) 1
|
||||
else value.hashCode() * 31
|
||||
}
|
||||
}
|
||||
"""
|
||||
@ -102,9 +102,7 @@ internal abstract class ${ktType.standardName}ValueImpl : ${ktType.standardName}
|
||||
object Setting_value_PrimitivesImplCodegen : RegionCodegen("_Setting.value.kt"), DefaultInvoke {
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) = super.startIndependent()
|
||||
|
||||
override val defaultInvokeArgs: List<KtType>
|
||||
get() = KtPrimitives + KtString
|
||||
override val defaultInvokeArgs: List<KtType> = KtPrimitives + KtString
|
||||
|
||||
override fun StringBuilder.apply(ktType: KtType) {
|
||||
appendKCode(
|
||||
@ -127,9 +125,7 @@ internal fun Setting.${ktType.lowerCaseName}ValueImpl(): SerializerAwareValue<${
|
||||
object Setting_valueImplPrimitiveCodegen : RegionCodegen("_Setting.value.kt"), DefaultInvoke {
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) = super.startIndependent()
|
||||
|
||||
override val defaultInvokeArgs: List<KtType>
|
||||
get() = KtPrimitives + KtString
|
||||
override val defaultInvokeArgs: List<KtType> = KtPrimitives + KtString
|
||||
|
||||
override fun StringBuilder.apply(ktType: KtType) {
|
||||
appendKCode(
|
||||
|
@ -15,6 +15,7 @@ import kotlinx.serialization.*
|
||||
import kotlinx.serialization.builtins.MapSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import net.mamoe.mirai.console.setting.internal.cast
|
||||
import net.mamoe.mirai.console.setting.internal.isOdd
|
||||
import net.mamoe.mirai.console.setting.internal.valueFromKTypeImpl
|
||||
import net.mamoe.mirai.console.setting.internal.valueImpl
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
@ -22,7 +23,7 @@ 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 java.util.*
|
||||
import net.mamoe.yamlkt.YamlNullableDynamicSerializer
|
||||
import kotlin.internal.LowPriorityInOverloadResolution
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.KType
|
||||
@ -39,7 +40,7 @@ abstract class Setting : SettingImpl() {
|
||||
property: KProperty<*>
|
||||
): SerializerAwareValue<T> {
|
||||
val name = property.serialName
|
||||
valueNodes.put(name, Node(name, this, this.serializer))
|
||||
valueNodes.add(Node(name, this, this.serializer))
|
||||
return this
|
||||
}
|
||||
|
||||
@ -55,29 +56,82 @@ internal val KProperty<*>.serialName: String get() = this.findAnnotation<SerialN
|
||||
*/
|
||||
// TODO move to internal package.
|
||||
internal abstract class SettingImpl {
|
||||
internal fun findNodeInstance(name: String): Node<*>? = valueNodes[name]
|
||||
internal fun findNodeInstance(name: String): Node<*>? = valueNodes.firstOrNull { it.serialName == name }
|
||||
|
||||
internal class Node<T>(
|
||||
internal data class Node<T>(
|
||||
val serialName: String,
|
||||
val value: Value<T>,
|
||||
val updaterSerializer: KSerializer<Unit>
|
||||
)
|
||||
|
||||
internal val valueNodes: MutableMap<String, Node<*>> = Collections.synchronizedMap(mutableMapOf())
|
||||
internal val valueNodes: MutableList<Node<*>> = mutableListOf()
|
||||
|
||||
internal open val updaterSerializer: KSerializer<Unit> by lazy {
|
||||
val actual = MapSerializer(String.serializer(), String.serializer())
|
||||
|
||||
object : KSerializer<Unit> {
|
||||
override val descriptor: SerialDescriptor
|
||||
get() = actual.descriptor
|
||||
override val descriptor: SerialDescriptor get() = settingUpdaterSerializerDescriptor
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun deserialize(decoder: Decoder) {
|
||||
actual.deserialize(decoder)
|
||||
val descriptor = descriptor
|
||||
with(decoder.beginStructure(descriptor, *settingUpdaterSerializerTypeArguments)) {
|
||||
if (decodeSequentially()) {
|
||||
var index = 0
|
||||
repeat(decodeCollectionSize(descriptor)) {
|
||||
val serialName = decodeSerializableElement(descriptor, index++, String.serializer())
|
||||
val node = findNodeInstance(serialName)
|
||||
if (node == null) {
|
||||
decodeSerializableElement(descriptor, index++, YamlNullableDynamicSerializer)
|
||||
} else {
|
||||
decodeSerializableElement(descriptor, index++, node.updaterSerializer)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
outerLoop@ while (true) {
|
||||
var serialName: String? = null
|
||||
innerLoop@ while (true) {
|
||||
val index = decodeElementIndex(descriptor)
|
||||
if (index == CompositeDecoder.READ_DONE) {
|
||||
check(serialName == null) { "name must be null at this moment." }
|
||||
break@outerLoop
|
||||
}
|
||||
|
||||
if (!index.isOdd()) { // key
|
||||
check(serialName == null) { "name must be null at this moment" }
|
||||
serialName = decodeSerializableElement(descriptor, index, String.serializer())
|
||||
} else {
|
||||
check(serialName != null) { "name must not be null at this moment" }
|
||||
|
||||
val node = findNodeInstance(serialName)
|
||||
if (node == null) {
|
||||
decodeSerializableElement(descriptor, index, YamlNullableDynamicSerializer)
|
||||
} else {
|
||||
decodeSerializableElement(descriptor, index, node.updaterSerializer)
|
||||
}
|
||||
|
||||
|
||||
break@innerLoop
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
endStructure(descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun serialize(encoder: Encoder, value: Unit) {
|
||||
TODO()
|
||||
val descriptor = descriptor
|
||||
with(encoder.beginCollection(descriptor, valueNodes.size, *settingUpdaterSerializerTypeArguments)) {
|
||||
var index = 0
|
||||
|
||||
// val vSerializer = settingUpdaterSerializerTypeArguments[1] as KSerializer<Any?>
|
||||
valueNodes.forEach { (serialName, _, valueSerializer) ->
|
||||
encodeSerializableElement(descriptor, index++, String.serializer(), serialName)
|
||||
encodeSerializableElement(descriptor, index++, valueSerializer, Unit)
|
||||
}
|
||||
endStructure(descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -91,6 +145,13 @@ internal abstract class SettingImpl {
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val ABSENT_STUB = Any()
|
||||
|
||||
private val settingUpdaterSerializerTypeArguments = arrayOf(String.serializer(), YamlNullableDynamicSerializer)
|
||||
private val settingUpdaterSerializerDescriptor =
|
||||
MapSerializer(settingUpdaterSerializerTypeArguments[0], settingUpdaterSerializerTypeArguments[1]).descriptor
|
||||
|
||||
val allFlow = Yaml(
|
||||
YamlConfiguration(
|
||||
nonStrictNullability = true,
|
||||
@ -124,7 +185,8 @@ fun Setting.value(default: Int): SerializerAwareValue<Int> = valueImpl(default)
|
||||
@LowPriorityInOverloadResolution
|
||||
@MiraiExperimentalAPI
|
||||
@OptIn(ExperimentalStdlibApi::class) // stable in 1.4
|
||||
inline fun <reified T> Setting.valueReified(default: T): SerializableValue<T> = valueFromKTypeImpl(typeOf<T>()).cast()
|
||||
inline fun <reified T> Setting.valueReified(default: T): SerializerAwareValue<T> =
|
||||
valueFromKTypeImpl(typeOf<T>()).cast()
|
||||
|
||||
@MiraiExperimentalAPI
|
||||
fun <T> Setting.valueFromKType(type: KType): SerializableValue<T> = valueFromKTypeImpl(type).cast()
|
||||
fun <T> Setting.valueFromKType(type: KType): SerializerAwareValue<T> = valueFromKTypeImpl(type).cast()
|
@ -15,6 +15,7 @@ import kotlinx.serialization.BinaryFormat
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.StringFormat
|
||||
import net.mamoe.mirai.console.setting.internal.map
|
||||
import net.mamoe.mirai.console.setting.internal.setValueBySerializer
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
@ -36,17 +37,22 @@ interface Value<T> {
|
||||
* Typically returned by [Setting.value] functions.
|
||||
*/
|
||||
class SerializableValue<T>(
|
||||
delegate: Value<T>,
|
||||
private val delegate: Value<T>,
|
||||
/**
|
||||
* The serializer used to update and dump [delegate]
|
||||
*/
|
||||
override val serializer: KSerializer<Unit>
|
||||
) : Value<T> by delegate, SerializerAwareValue<T>
|
||||
) : Value<T> by delegate, SerializerAwareValue<T> {
|
||||
override fun toString(): String = delegate.toString()
|
||||
}
|
||||
|
||||
fun <T> Value<T>.serializableValueWith(
|
||||
serializer: KSerializer<T>
|
||||
): SerializableValue<T> {
|
||||
return SerializableValue(this, serializer.map(serializer = { this.value }, deserializer = { this.value = it }))
|
||||
return SerializableValue(
|
||||
this,
|
||||
serializer.map(serializer = { this.value }, deserializer = { this.setValueBySerializer(it) })
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -136,7 +142,6 @@ interface BooleanValue : PrimitiveValue<Boolean>
|
||||
*/
|
||||
interface StringValue : PrimitiveValue<String>
|
||||
|
||||
|
||||
//// endregion PrimitiveValues CODEGEN ////
|
||||
|
||||
|
||||
|
@ -25,7 +25,7 @@ internal fun <T> Setting.createCompositeSetValueImpl(tToValue: (T) -> Value<T>):
|
||||
|
||||
internal abstract class CompositeSetValueImpl<T>(
|
||||
tToValue: (T) -> Value<T> // should override onChanged
|
||||
) : CompositeSetValue<T> {
|
||||
) : CompositeSetValue<T>, AbstractValueImpl<Set<T>>() {
|
||||
private val internalSet: MutableSet<Value<T>> = mutableSetOf()
|
||||
|
||||
private var _value: Set<T> = internalSet.shadowMap({ it.value }, tToValue).observable { onChanged() }
|
||||
@ -34,12 +34,30 @@ internal abstract class CompositeSetValueImpl<T>(
|
||||
get() = _value
|
||||
set(v) {
|
||||
if (_value != v) {
|
||||
@Suppress("LocalVariableName")
|
||||
val _value = _value as MutableSet<T>
|
||||
_value.clear()
|
||||
_value.addAll(v)
|
||||
onChanged()
|
||||
_value = v
|
||||
}
|
||||
}
|
||||
|
||||
override fun setValueBySerializer(value: Set<T>) {
|
||||
val thisValue = this.value
|
||||
if (!thisValue.tryPatch(value)) {
|
||||
this.value = value // deep set
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onChanged()
|
||||
override fun toString(): String = _value.toString()
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is CompositeSetValueImpl<*> && other::class.java == this::class.java && other._value == this._value
|
||||
|
||||
override fun hashCode(): Int {
|
||||
val value = _value
|
||||
return value.hashCode() * 31 + super.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -54,21 +72,39 @@ internal fun <T> Setting.createCompositeListValueImpl(tToValue: (T) -> Value<T>)
|
||||
|
||||
internal abstract class CompositeListValueImpl<T>(
|
||||
tToValue: (T) -> Value<T> // should override onChanged
|
||||
) : CompositeListValue<T> {
|
||||
) : CompositeListValue<T>, AbstractValueImpl<List<T>>() {
|
||||
private val internalList: MutableList<Value<T>> = mutableListOf()
|
||||
|
||||
private var _value: List<T> = internalList.shadowMap({ it.value }, tToValue).observable { onChanged() }
|
||||
private val _value: List<T> = internalList.shadowMap({ it.value }, tToValue).observable { onChanged() }
|
||||
|
||||
override var value: List<T>
|
||||
get() = _value
|
||||
set(v) {
|
||||
if (_value != v) {
|
||||
@Suppress("LocalVariableName")
|
||||
val _value = _value as MutableList<T>
|
||||
_value.clear()
|
||||
_value.addAll(v)
|
||||
onChanged()
|
||||
_value = v
|
||||
}
|
||||
}
|
||||
|
||||
override fun setValueBySerializer(value: List<T>) {
|
||||
val thisValue = this.value
|
||||
if (!thisValue.tryPatch(value)) {
|
||||
this.value = value // deep set
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onChanged()
|
||||
override fun toString(): String = _value.toString()
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is CompositeListValueImpl<*> && other::class.java == this::class.java && other._value == this._value
|
||||
|
||||
override fun hashCode(): Int {
|
||||
val value = _value
|
||||
return value.hashCode() * 31 + super.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
// workaround to a type inference bug
|
||||
@ -77,28 +113,85 @@ internal fun <K, V> Setting.createCompositeMapValueImpl(
|
||||
vToValue: (V) -> Value<V>
|
||||
): CompositeMapValueImpl<K, V> {
|
||||
return object : CompositeMapValueImpl<K, V>(kToValue, vToValue) {
|
||||
override fun onChanged() {
|
||||
this@createCompositeMapValueImpl.onValueChanged(this)
|
||||
}
|
||||
override fun onChanged() = this@createCompositeMapValueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class CompositeMapValueImpl<K, V>(
|
||||
kToValue: (K) -> Value<K>, // should override onChanged
|
||||
vToValue: (V) -> Value<V> // should override onChanged
|
||||
) : CompositeMapValue<K, V> {
|
||||
) : CompositeMapValue<K, V>, AbstractValueImpl<Map<K, V>>() {
|
||||
private val internalList: MutableMap<Value<K>, Value<V>> = mutableMapOf()
|
||||
|
||||
private var _value: Map<K, V> =
|
||||
private var _value: MutableMap<K, V> =
|
||||
internalList.shadowMap({ it.value }, kToValue, { it.value }, vToValue).observable { onChanged() }
|
||||
override var value: Map<K, V>
|
||||
get() = _value
|
||||
set(v) {
|
||||
if (_value != v) {
|
||||
@Suppress("LocalVariableName")
|
||||
val _value = _value
|
||||
_value.clear()
|
||||
_value.putAll(v)
|
||||
onChanged()
|
||||
_value = v
|
||||
}
|
||||
}
|
||||
|
||||
override fun setValueBySerializer(value: Map<K, V>) {
|
||||
val thisValue = this.value as MutableMap<K, V>
|
||||
if (!thisValue.tryPatch(value)) {
|
||||
this.value = value // deep set
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onChanged()
|
||||
override fun toString(): String = _value.toString()
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is CompositeMapValueImpl<*, *> && other::class.java == this::class.java && other._value == this._value
|
||||
|
||||
override fun hashCode(): Int {
|
||||
val value = _value
|
||||
return value.hashCode() * 31 + super.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <K, V> MutableMap<K, V>.patchImpl(_new: Map<K, V>) {
|
||||
val new = _new.toMutableMap()
|
||||
val iterator = this.iterator()
|
||||
for (entry in iterator) {
|
||||
val newValue = new.remove(entry.key)
|
||||
|
||||
if (newValue != null) {
|
||||
// has replacer
|
||||
if (entry.value?.tryPatch(newValue) != true) {
|
||||
// patch not supported, or old value is null
|
||||
entry.setValue(newValue)
|
||||
} // else: patched, no remove
|
||||
} else {
|
||||
// no replacer
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
putAll(new)
|
||||
}
|
||||
|
||||
internal fun <C : MutableCollection<E>, E> C.patchImpl(_new: Collection<E>) {
|
||||
this.retainAll(_new)
|
||||
}
|
||||
|
||||
/**
|
||||
* True if successfully patched
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal fun Any.tryPatch(any: Any): Boolean = when {
|
||||
this is MutableCollection<*> && any is Collection<*> -> {
|
||||
(this as MutableCollection<Any?>).patchImpl(any as Collection<Any?>)
|
||||
true
|
||||
}
|
||||
this is MutableMap<*, *> && any is Map<*, *> -> {
|
||||
(this as MutableMap<Any?, Any?>).patchImpl(any as Map<Any?, Any?>)
|
||||
true
|
||||
}
|
||||
this is Value<*> && any is Value<*> -> any.value?.let { otherValue -> this.value?.tryPatch(otherValue) } == true
|
||||
else -> false
|
||||
}
|
@ -13,7 +13,7 @@ package net.mamoe.mirai.console.setting.internal
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.builtins.*
|
||||
import net.mamoe.mirai.console.setting.SerializableValue
|
||||
import net.mamoe.mirai.console.setting.SerializerAwareValue
|
||||
import net.mamoe.mirai.console.setting.Setting
|
||||
import net.mamoe.mirai.console.setting.serializableValueWith
|
||||
import net.mamoe.mirai.console.setting.valueFromKType
|
||||
@ -22,43 +22,52 @@ import net.mamoe.yamlkt.YamlNullableDynamicSerializer
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
|
||||
private val primitiveCollectionsImplemented by lazy {
|
||||
false
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@Suppress("UnsafeCall", "SMARTCAST_IMPOSSIBLE", "UNCHECKED_CAST")
|
||||
internal fun Setting.valueFromKTypeImpl(type: KType): SerializableValue<*> {
|
||||
internal fun Setting.valueFromKTypeImpl(type: KType): SerializerAwareValue<*> {
|
||||
val classifier = type.classifier
|
||||
require(classifier is KClass<*>)
|
||||
|
||||
if (classifier.isPrimitiveOrBuiltInSerializableValue()) {
|
||||
TODO("是基础类型, 可以直接创建 ValueImpl. ")
|
||||
return valueImplPrimitive(classifier) as SerializerAwareValue<*>
|
||||
}
|
||||
|
||||
// 复合类型
|
||||
|
||||
when (classifier) {
|
||||
Map::class -> {
|
||||
MutableMap::class,
|
||||
Map::class
|
||||
-> {
|
||||
val keyClass = type.arguments[0].type?.classifier
|
||||
require(keyClass is KClass<*>)
|
||||
|
||||
val valueClass = type.arguments[1].type?.classifier
|
||||
require(valueClass is KClass<*>)
|
||||
|
||||
if (keyClass.isPrimitiveOrBuiltInSerializableValue() && valueClass.isPrimitiveOrBuiltInSerializableValue()) {
|
||||
if (primitiveCollectionsImplemented && keyClass.isPrimitiveOrBuiltInSerializableValue() && valueClass.isPrimitiveOrBuiltInSerializableValue()) {
|
||||
// PrimitiveIntIntMap
|
||||
// ...
|
||||
TODO()
|
||||
} else {
|
||||
return createCompositeMapValueImpl<Any?, Any?>(
|
||||
kToValue = { valueFromKType(type.arguments[0].type!!) },
|
||||
vToValue = { valueFromKType(type.arguments[1].type!!) }
|
||||
kToValue = { k -> valueFromKType<Any?>(type.arguments[0].type!!).also { it.value = k } },
|
||||
vToValue = { v -> valueFromKType<Any?>(type.arguments[1].type!!).also { it.value = v } }
|
||||
).serializableValueWith(serializerMirai(type) as KSerializer<Map<Any?, Any?>>) // erased
|
||||
}
|
||||
}
|
||||
List::class -> {
|
||||
Collection::class,
|
||||
MutableCollection::class,
|
||||
MutableList::class,
|
||||
List::class
|
||||
-> {
|
||||
val elementClass = type.arguments[0].type?.classifier
|
||||
require(elementClass is KClass<*>)
|
||||
|
||||
if (elementClass.isPrimitiveOrBuiltInSerializableValue()) {
|
||||
if (primitiveCollectionsImplemented && elementClass.isPrimitiveOrBuiltInSerializableValue()) {
|
||||
// PrimitiveIntList
|
||||
// ...
|
||||
TODO()
|
||||
@ -67,11 +76,13 @@ internal fun Setting.valueFromKTypeImpl(type: KType): SerializableValue<*> {
|
||||
.serializableValueWith(serializerMirai(type) as KSerializer<List<Any?>>)
|
||||
}
|
||||
}
|
||||
Set::class -> {
|
||||
MutableSet::class,
|
||||
Set::class
|
||||
-> {
|
||||
val elementClass = type.arguments[0].type?.classifier
|
||||
require(elementClass is KClass<*>)
|
||||
|
||||
if (elementClass.isPrimitiveOrBuiltInSerializableValue()) {
|
||||
if (primitiveCollectionsImplemented && elementClass.isPrimitiveOrBuiltInSerializableValue()) {
|
||||
// PrimitiveIntSet
|
||||
// ...
|
||||
TODO()
|
||||
@ -85,7 +96,6 @@ internal fun Setting.valueFromKTypeImpl(type: KType): SerializableValue<*> {
|
||||
}
|
||||
|
||||
internal fun KClass<*>.isPrimitiveOrBuiltInSerializableValue(): Boolean {
|
||||
return false // debug
|
||||
when (this) {
|
||||
Byte::class, Short::class, Int::class, Long::class,
|
||||
Boolean::class,
|
||||
|
@ -0,0 +1,346 @@
|
||||
/*
|
||||
* 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.internal
|
||||
|
||||
import kotlinx.serialization.Decoder
|
||||
import kotlinx.serialization.Encoder
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.SerialDescriptor
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import net.mamoe.mirai.console.setting.*
|
||||
|
||||
/**
|
||||
* The super class to all ValueImpl s
|
||||
*/
|
||||
internal abstract class AbstractValueImpl<T> : Value<T> {
|
||||
open fun setValueBySerializer(value: T) {
|
||||
this.value = value
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <T> Value<T>.setValueBySerializer(value: T) = (this as AbstractValueImpl<T>).setValueBySerializer(value)
|
||||
|
||||
//// region PrimitiveValuesImpl CODEGEN ////
|
||||
|
||||
internal abstract class ByteValueImpl : ByteValue, SerializerAwareValue<Byte>, KSerializer<Unit>,
|
||||
AbstractValueImpl<Byte> {
|
||||
constructor()
|
||||
constructor(default: Byte) {
|
||||
_value = default
|
||||
}
|
||||
|
||||
private var _value: Byte? = null
|
||||
|
||||
final override var value: Byte
|
||||
get() = _value ?: error("ByteValue.value should be initialized before get.")
|
||||
set(v) {
|
||||
if (v != this._value) {
|
||||
this._value = v
|
||||
onChanged()
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onChanged()
|
||||
|
||||
final override val serializer: KSerializer<Unit> get() = this
|
||||
final override val descriptor: SerialDescriptor get() = BuiltInSerializerConstants.ByteSerializerDescriptor
|
||||
final override fun serialize(encoder: Encoder, value: Unit) = Byte.serializer().serialize(encoder, this.value)
|
||||
final override fun deserialize(decoder: Decoder) = setValueBySerializer(Byte.serializer().deserialize(decoder))
|
||||
override fun toString(): String = _value?.toString() ?: "ByteValue.value not yet initialized."
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is ByteValueImpl && other::class.java == this::class.java && other._value == this._value
|
||||
|
||||
override fun hashCode(): Int {
|
||||
val value = _value
|
||||
return if (value == null) 1
|
||||
else value.hashCode() * 31
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class ShortValueImpl : ShortValue, SerializerAwareValue<Short>, KSerializer<Unit>,
|
||||
AbstractValueImpl<Short> {
|
||||
constructor()
|
||||
constructor(default: Short) {
|
||||
_value = default
|
||||
}
|
||||
|
||||
private var _value: Short? = null
|
||||
|
||||
final override var value: Short
|
||||
get() = _value ?: error("ShortValue.value should be initialized before get.")
|
||||
set(v) {
|
||||
if (v != this._value) {
|
||||
this._value = v
|
||||
onChanged()
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onChanged()
|
||||
|
||||
final override val serializer: KSerializer<Unit> get() = this
|
||||
final override val descriptor: SerialDescriptor get() = BuiltInSerializerConstants.ShortSerializerDescriptor
|
||||
final override fun serialize(encoder: Encoder, value: Unit) = Short.serializer().serialize(encoder, this.value)
|
||||
final override fun deserialize(decoder: Decoder) = setValueBySerializer(Short.serializer().deserialize(decoder))
|
||||
override fun toString(): String = _value?.toString() ?: "ShortValue.value not yet initialized."
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is ShortValueImpl && other::class.java == this::class.java && other._value == this._value
|
||||
|
||||
override fun hashCode(): Int {
|
||||
val value = _value
|
||||
return if (value == null) 1
|
||||
else value.hashCode() * 31
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class IntValueImpl : IntValue, SerializerAwareValue<Int>, KSerializer<Unit>, AbstractValueImpl<Int> {
|
||||
constructor()
|
||||
constructor(default: Int) {
|
||||
_value = default
|
||||
}
|
||||
|
||||
private var _value: Int? = null
|
||||
|
||||
final override var value: Int
|
||||
get() = _value ?: error("IntValue.value should be initialized before get.")
|
||||
set(v) {
|
||||
if (v != this._value) {
|
||||
this._value = v
|
||||
onChanged()
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onChanged()
|
||||
|
||||
final override val serializer: KSerializer<Unit> get() = this
|
||||
final override val descriptor: SerialDescriptor get() = BuiltInSerializerConstants.IntSerializerDescriptor
|
||||
final override fun serialize(encoder: Encoder, value: Unit) = Int.serializer().serialize(encoder, this.value)
|
||||
final override fun deserialize(decoder: Decoder) = setValueBySerializer(Int.serializer().deserialize(decoder))
|
||||
override fun toString(): String = _value?.toString() ?: "IntValue.value not yet initialized."
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is IntValueImpl && other::class.java == this::class.java && other._value == this._value
|
||||
|
||||
override fun hashCode(): Int {
|
||||
val value = _value
|
||||
return if (value == null) 1
|
||||
else value.hashCode() * 31
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class LongValueImpl : LongValue, SerializerAwareValue<Long>, KSerializer<Unit>,
|
||||
AbstractValueImpl<Long> {
|
||||
constructor()
|
||||
constructor(default: Long) {
|
||||
_value = default
|
||||
}
|
||||
|
||||
private var _value: Long? = null
|
||||
|
||||
final override var value: Long
|
||||
get() = _value ?: error("LongValue.value should be initialized before get.")
|
||||
set(v) {
|
||||
if (v != this._value) {
|
||||
this._value = v
|
||||
onChanged()
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onChanged()
|
||||
|
||||
final override val serializer: KSerializer<Unit> get() = this
|
||||
final override val descriptor: SerialDescriptor get() = BuiltInSerializerConstants.LongSerializerDescriptor
|
||||
final override fun serialize(encoder: Encoder, value: Unit) = Long.serializer().serialize(encoder, this.value)
|
||||
final override fun deserialize(decoder: Decoder) = setValueBySerializer(Long.serializer().deserialize(decoder))
|
||||
override fun toString(): String = _value?.toString() ?: "LongValue.value not yet initialized."
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is LongValueImpl && other::class.java == this::class.java && other._value == this._value
|
||||
|
||||
override fun hashCode(): Int {
|
||||
val value = _value
|
||||
return if (value == null) 1
|
||||
else value.hashCode() * 31
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class FloatValueImpl : FloatValue, SerializerAwareValue<Float>, KSerializer<Unit>,
|
||||
AbstractValueImpl<Float> {
|
||||
constructor()
|
||||
constructor(default: Float) {
|
||||
_value = default
|
||||
}
|
||||
|
||||
private var _value: Float? = null
|
||||
|
||||
final override var value: Float
|
||||
get() = _value ?: error("FloatValue.value should be initialized before get.")
|
||||
set(v) {
|
||||
if (v != this._value) {
|
||||
this._value = v
|
||||
onChanged()
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onChanged()
|
||||
|
||||
final override val serializer: KSerializer<Unit> get() = this
|
||||
final override val descriptor: SerialDescriptor get() = BuiltInSerializerConstants.FloatSerializerDescriptor
|
||||
final override fun serialize(encoder: Encoder, value: Unit) = Float.serializer().serialize(encoder, this.value)
|
||||
final override fun deserialize(decoder: Decoder) = setValueBySerializer(Float.serializer().deserialize(decoder))
|
||||
override fun toString(): String = _value?.toString() ?: "FloatValue.value not yet initialized."
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is FloatValueImpl && other::class.java == this::class.java && other._value == this._value
|
||||
|
||||
override fun hashCode(): Int {
|
||||
val value = _value
|
||||
return if (value == null) 1
|
||||
else value.hashCode() * 31
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class DoubleValueImpl : DoubleValue, SerializerAwareValue<Double>, KSerializer<Unit>,
|
||||
AbstractValueImpl<Double> {
|
||||
constructor()
|
||||
constructor(default: Double) {
|
||||
_value = default
|
||||
}
|
||||
|
||||
private var _value: Double? = null
|
||||
|
||||
final override var value: Double
|
||||
get() = _value ?: error("DoubleValue.value should be initialized before get.")
|
||||
set(v) {
|
||||
if (v != this._value) {
|
||||
this._value = v
|
||||
onChanged()
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onChanged()
|
||||
|
||||
final override val serializer: KSerializer<Unit> get() = this
|
||||
final override val descriptor: SerialDescriptor get() = BuiltInSerializerConstants.DoubleSerializerDescriptor
|
||||
final override fun serialize(encoder: Encoder, value: Unit) = Double.serializer().serialize(encoder, this.value)
|
||||
final override fun deserialize(decoder: Decoder) = setValueBySerializer(Double.serializer().deserialize(decoder))
|
||||
override fun toString(): String = _value?.toString() ?: "DoubleValue.value not yet initialized."
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is DoubleValueImpl && other::class.java == this::class.java && other._value == this._value
|
||||
|
||||
override fun hashCode(): Int {
|
||||
val value = _value
|
||||
return if (value == null) 1
|
||||
else value.hashCode() * 31
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class CharValueImpl : CharValue, SerializerAwareValue<Char>, KSerializer<Unit>,
|
||||
AbstractValueImpl<Char> {
|
||||
constructor()
|
||||
constructor(default: Char) {
|
||||
_value = default
|
||||
}
|
||||
|
||||
private var _value: Char? = null
|
||||
|
||||
final override var value: Char
|
||||
get() = _value ?: error("CharValue.value should be initialized before get.")
|
||||
set(v) {
|
||||
if (v != this._value) {
|
||||
this._value = v
|
||||
onChanged()
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onChanged()
|
||||
|
||||
final override val serializer: KSerializer<Unit> get() = this
|
||||
final override val descriptor: SerialDescriptor get() = BuiltInSerializerConstants.CharSerializerDescriptor
|
||||
final override fun serialize(encoder: Encoder, value: Unit) = Char.serializer().serialize(encoder, this.value)
|
||||
final override fun deserialize(decoder: Decoder) = setValueBySerializer(Char.serializer().deserialize(decoder))
|
||||
override fun toString(): String = _value?.toString() ?: "CharValue.value not yet initialized."
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is CharValueImpl && other::class.java == this::class.java && other._value == this._value
|
||||
|
||||
override fun hashCode(): Int {
|
||||
val value = _value
|
||||
return if (value == null) 1
|
||||
else value.hashCode() * 31
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class BooleanValueImpl : BooleanValue, SerializerAwareValue<Boolean>, KSerializer<Unit>,
|
||||
AbstractValueImpl<Boolean> {
|
||||
constructor()
|
||||
constructor(default: Boolean) {
|
||||
_value = default
|
||||
}
|
||||
|
||||
private var _value: Boolean? = null
|
||||
|
||||
final override var value: Boolean
|
||||
get() = _value ?: error("BooleanValue.value should be initialized before get.")
|
||||
set(v) {
|
||||
if (v != this._value) {
|
||||
this._value = v
|
||||
onChanged()
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onChanged()
|
||||
|
||||
final override val serializer: KSerializer<Unit> get() = this
|
||||
final override val descriptor: SerialDescriptor get() = BuiltInSerializerConstants.BooleanSerializerDescriptor
|
||||
final override fun serialize(encoder: Encoder, value: Unit) = Boolean.serializer().serialize(encoder, this.value)
|
||||
final override fun deserialize(decoder: Decoder) = setValueBySerializer(Boolean.serializer().deserialize(decoder))
|
||||
override fun toString(): String = _value?.toString() ?: "BooleanValue.value not yet initialized."
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is BooleanValueImpl && other::class.java == this::class.java && other._value == this._value
|
||||
|
||||
override fun hashCode(): Int {
|
||||
val value = _value
|
||||
return if (value == null) 1
|
||||
else value.hashCode() * 31
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class StringValueImpl : StringValue, SerializerAwareValue<String>, KSerializer<Unit>,
|
||||
AbstractValueImpl<String> {
|
||||
constructor()
|
||||
constructor(default: String) {
|
||||
_value = default
|
||||
}
|
||||
|
||||
private var _value: String? = null
|
||||
|
||||
final override var value: String
|
||||
get() = _value ?: error("StringValue.value should be initialized before get.")
|
||||
set(v) {
|
||||
if (v != this._value) {
|
||||
this._value = v
|
||||
onChanged()
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onChanged()
|
||||
|
||||
final override val serializer: KSerializer<Unit> get() = this
|
||||
final override val descriptor: SerialDescriptor get() = BuiltInSerializerConstants.StringSerializerDescriptor
|
||||
final override fun serialize(encoder: Encoder, value: Unit) = String.serializer().serialize(encoder, this.value)
|
||||
final override fun deserialize(decoder: Decoder) = setValueBySerializer(String.serializer().deserialize(decoder))
|
||||
override fun toString(): String = _value ?: "StringValue.value not yet initialized."
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is StringValueImpl && other::class.java == this::class.java && other._value == this._value
|
||||
|
||||
override fun hashCode(): Int {
|
||||
val value = _value
|
||||
return if (value == null) 1
|
||||
else value.hashCode() * 31
|
||||
}
|
||||
}
|
||||
|
||||
//// endregion PrimitiveValuesImpl CODEGEN ////
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* 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.internal
|
||||
|
||||
import kotlinx.serialization.Decoder
|
||||
import kotlinx.serialization.Encoder
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.SerialDescriptor
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import net.mamoe.mirai.console.setting.IntValue
|
||||
import net.mamoe.mirai.console.setting.SerializerAwareValue
|
||||
|
||||
|
||||
//// region PrimitiveValues CODEGEN ////
|
||||
|
||||
// TODO: 2020/6/21 CODEGEN
|
||||
|
||||
internal abstract class IntValueImpl : IntValue, SerializerAwareValue<Int>, KSerializer<Unit> {
|
||||
constructor()
|
||||
constructor(default: Int) {
|
||||
_value = default
|
||||
}
|
||||
|
||||
private var _value: Int? = null
|
||||
|
||||
final override var value: Int
|
||||
get() = _value ?: error("IntValue.value should be initialized before get.")
|
||||
set(v) {
|
||||
if (v != this._value) {
|
||||
this._value = v
|
||||
onChanged()
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onChanged()
|
||||
|
||||
final override val serializer: KSerializer<Unit> get() = this
|
||||
final override val descriptor: SerialDescriptor get() = BuiltInSerializerConstants.IntSerializerDescriptor
|
||||
final override fun serialize(encoder: Encoder, value: Unit) = Int.serializer().serialize(encoder, this.value)
|
||||
final override fun deserialize(decoder: Decoder) {
|
||||
value = Int.serializer().deserialize(decoder)
|
||||
}
|
||||
}
|
||||
|
||||
//// endregion PrimitiveValues CODEGEN ////
|
@ -12,10 +12,11 @@ package net.mamoe.mirai.console.setting.internal
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import net.mamoe.mirai.console.setting.SerializerAwareValue
|
||||
import net.mamoe.mirai.console.setting.Setting
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
||||
internal object BuiltInSerializerConstants {
|
||||
//// region BuiltInSerializerConstants primitives CODEGEN ////
|
||||
//// region BuiltInSerializerConstantsPrimitives CODEGEN ////
|
||||
|
||||
@JvmStatic
|
||||
val ByteSerializerDescriptor = Byte.serializer().descriptor
|
||||
@ -44,13 +45,55 @@ internal object BuiltInSerializerConstants {
|
||||
@JvmStatic
|
||||
val StringSerializerDescriptor = String.serializer().descriptor
|
||||
|
||||
|
||||
//// endregion BuiltInSerializerConstants primitives CODEGEN ////
|
||||
//// endregion BuiltInSerializerConstantsPrimitives CODEGEN ////
|
||||
}
|
||||
|
||||
//// region Setting.value primitives impl CODEGEN ////
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal fun <T : Any> Setting.valueImplPrimitive(kClass: KClass<T>): SerializerAwareValue<T>? {
|
||||
return when (kClass) {
|
||||
//// region Setting_valueImplPrimitive CODEGEN ////
|
||||
|
||||
// TODO: 2020/6/21 CODEGEN
|
||||
Byte::class -> byteValueImpl()
|
||||
Short::class -> shortValueImpl()
|
||||
Int::class -> intValueImpl()
|
||||
Long::class -> longValueImpl()
|
||||
Float::class -> floatValueImpl()
|
||||
Double::class -> doubleValueImpl()
|
||||
Char::class -> charValueImpl()
|
||||
Boolean::class -> booleanValueImpl()
|
||||
String::class -> stringValueImpl()
|
||||
|
||||
//// endregion Setting_valueImplPrimitive CODEGEN ////
|
||||
else -> error("Internal error: unexpected type passed: ${kClass.qualifiedName}")
|
||||
} as SerializerAwareValue<T>?
|
||||
}
|
||||
|
||||
|
||||
//// region Setting_value_PrimitivesImpl CODEGEN ////
|
||||
|
||||
internal fun Setting.valueImpl(default: Byte): SerializerAwareValue<Byte> {
|
||||
return object : ByteValueImpl(default) {
|
||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.byteValueImpl(): SerializerAwareValue<Byte> {
|
||||
return object : ByteValueImpl() {
|
||||
override fun onChanged() = this@byteValueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Short): SerializerAwareValue<Short> {
|
||||
return object : ShortValueImpl(default) {
|
||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.shortValueImpl(): SerializerAwareValue<Short> {
|
||||
return object : ShortValueImpl() {
|
||||
override fun onChanged() = this@shortValueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Int): SerializerAwareValue<Int> {
|
||||
return object : IntValueImpl(default) {
|
||||
@ -58,4 +101,82 @@ internal fun Setting.valueImpl(default: Int): SerializerAwareValue<Int> {
|
||||
}
|
||||
}
|
||||
|
||||
//// endregion Setting.value primitives impl CODEGEN ////
|
||||
internal fun Setting.intValueImpl(): SerializerAwareValue<Int> {
|
||||
return object : IntValueImpl() {
|
||||
override fun onChanged() = this@intValueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Long): SerializerAwareValue<Long> {
|
||||
return object : LongValueImpl(default) {
|
||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.longValueImpl(): SerializerAwareValue<Long> {
|
||||
return object : LongValueImpl() {
|
||||
override fun onChanged() = this@longValueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Float): SerializerAwareValue<Float> {
|
||||
return object : FloatValueImpl(default) {
|
||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.floatValueImpl(): SerializerAwareValue<Float> {
|
||||
return object : FloatValueImpl() {
|
||||
override fun onChanged() = this@floatValueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Double): SerializerAwareValue<Double> {
|
||||
return object : DoubleValueImpl(default) {
|
||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.doubleValueImpl(): SerializerAwareValue<Double> {
|
||||
return object : DoubleValueImpl() {
|
||||
override fun onChanged() = this@doubleValueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Char): SerializerAwareValue<Char> {
|
||||
return object : CharValueImpl(default) {
|
||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.charValueImpl(): SerializerAwareValue<Char> {
|
||||
return object : CharValueImpl() {
|
||||
override fun onChanged() = this@charValueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: Boolean): SerializerAwareValue<Boolean> {
|
||||
return object : BooleanValueImpl(default) {
|
||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.booleanValueImpl(): SerializerAwareValue<Boolean> {
|
||||
return object : BooleanValueImpl() {
|
||||
override fun onChanged() = this@booleanValueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.valueImpl(default: String): SerializerAwareValue<String> {
|
||||
return object : StringValueImpl(default) {
|
||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Setting.stringValueImpl(): SerializerAwareValue<String> {
|
||||
return object : StringValueImpl() {
|
||||
override fun onChanged() = this@stringValueImpl.onValueChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
//// endregion Setting_value_PrimitivesImpl CODEGEN ////
|
||||
|
@ -16,6 +16,8 @@ import kotlinx.serialization.serializer
|
||||
import net.mamoe.yamlkt.Yaml
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
// TODO: 2020/6/24 优化性能: 引入一个 comparator 之类来替代将 Int 包装为 Value<Int> 后进行 containsKey 比较的方法
|
||||
|
||||
internal inline fun <K, V, KR, VR> MutableMap<K, V>.shadowMap(
|
||||
crossinline kTransform: (K) -> KR,
|
||||
crossinline kTransformBack: (KR) -> K,
|
||||
@ -37,6 +39,13 @@ internal inline fun <K, V, KR, VR> MutableMap<K, V>.shadowMap(
|
||||
override val value: VR get() = entry.value.let(vTransform)
|
||||
override fun setValue(newValue: VR): VR =
|
||||
entry.setValue(newValue.let(vTransformBack)).let(vTransform)
|
||||
|
||||
override fun hashCode(): Int = 17 * 31 + (key?.hashCode() ?: 0) + (value?.hashCode() ?: 0)
|
||||
override fun toString(): String = "$key=$value"
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other !is Map.Entry<*, *>) return false
|
||||
return other.key == key && other.value == value
|
||||
}
|
||||
}
|
||||
} as ((MutableMap.MutableEntry<K, V>) -> MutableMap.MutableEntry<KR, VR>), // type inference bug
|
||||
transformBack = { entry ->
|
||||
@ -45,6 +54,13 @@ internal inline fun <K, V, KR, VR> MutableMap<K, V>.shadowMap(
|
||||
override val value: V get() = entry.value.let(vTransformBack)
|
||||
override fun setValue(newValue: V): V =
|
||||
entry.setValue(newValue.let(vTransform)).let(vTransformBack)
|
||||
|
||||
override fun hashCode(): Int = 17 * 31 + (key?.hashCode() ?: 0) + (value?.hashCode() ?: 0)
|
||||
override fun toString(): String = "$key=$value"
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other !is Map.Entry<*, *>) return false
|
||||
return other.key == key && other.value == value
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -64,6 +80,8 @@ internal inline fun <K, V, KR, VR> MutableMap<K, V>.shadowMap(
|
||||
}
|
||||
|
||||
override fun remove(key: KR): VR? = this@shadowMap.remove(key.let(kTransformBack))?.let(vTransform)
|
||||
override fun toString(): String = this@shadowMap.toString()
|
||||
override fun hashCode(): Int = this@shadowMap.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,6 +100,8 @@ internal inline fun <E, R> MutableCollection<E>.shadowMap(
|
||||
override fun hasNext(): Boolean = delegate.hasNext()
|
||||
override fun next(): R = delegate.next().let(transform)
|
||||
override fun remove() = delegate.remove()
|
||||
override fun toString(): String = delegate.toString()
|
||||
override fun hashCode(): Int = delegate.hashCode()
|
||||
}
|
||||
|
||||
override fun add(element: R): Boolean = this@shadowMap.add(element.let(transformBack))
|
||||
@ -92,6 +112,8 @@ internal inline fun <E, R> MutableCollection<E>.shadowMap(
|
||||
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))
|
||||
override fun toString(): String = this@shadowMap.toString()
|
||||
override fun hashCode(): Int = this@shadowMap.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,6 +134,8 @@ internal inline fun <E, R> MutableList<E>.shadowMap(
|
||||
override fun hasNext(): Boolean = delegate.hasNext()
|
||||
override fun next(): R = delegate.next().let(transform)
|
||||
override fun remove() = delegate.remove()
|
||||
override fun toString(): String = delegate.toString()
|
||||
override fun hashCode(): Int = delegate.hashCode()
|
||||
}
|
||||
|
||||
override fun lastIndexOf(element: R): Int = this@shadowMap.indexOfLast { it.let(transform) == element }
|
||||
@ -134,6 +158,8 @@ internal inline fun <E, R> MutableList<E>.shadowMap(
|
||||
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 toString(): String = delegate.toString()
|
||||
override fun hashCode(): Int = delegate.hashCode()
|
||||
}
|
||||
|
||||
override fun listIterator(index: Int): MutableListIterator<R> = object : MutableListIterator<R> {
|
||||
@ -147,6 +173,8 @@ internal inline fun <E, R> MutableList<E>.shadowMap(
|
||||
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 toString(): String = delegate.toString()
|
||||
override fun hashCode(): Int = delegate.hashCode()
|
||||
}
|
||||
|
||||
override fun remove(element: R): Boolean = this@shadowMap.removeIf { it.let(transform) == element }
|
||||
@ -158,6 +186,9 @@ internal inline fun <E, R> MutableList<E>.shadowMap(
|
||||
|
||||
override fun subList(fromIndex: Int, toIndex: Int): MutableList<R> =
|
||||
this@shadowMap.subList(fromIndex, toIndex).map(transform).toMutableList()
|
||||
|
||||
override fun toString(): String = this@shadowMap.toString()
|
||||
override fun hashCode(): Int = this@shadowMap.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,6 +208,8 @@ internal inline fun <E, R> MutableSet<E>.shadowMap(
|
||||
override fun hasNext(): Boolean = delegate.hasNext()
|
||||
override fun next(): R = delegate.next().let(transform)
|
||||
override fun remove() = delegate.remove()
|
||||
override fun toString(): String = delegate.toString()
|
||||
override fun hashCode(): Int = delegate.hashCode()
|
||||
}
|
||||
|
||||
override fun add(element: R): Boolean = this@shadowMap.add(element.let(transformBack))
|
||||
@ -186,6 +219,8 @@ internal inline fun <E, R> MutableSet<E>.shadowMap(
|
||||
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))
|
||||
override fun toString(): String = this@shadowMap.toString()
|
||||
override fun hashCode(): Int = this@shadowMap.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,6 +237,8 @@ internal inline fun <T> dynamicList(crossinline supplier: () -> List<T>): List<T
|
||||
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)
|
||||
override fun toString(): String = supplier().toString()
|
||||
override fun hashCode(): Int = supplier().hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,6 +249,8 @@ internal inline fun <T> dynamicSet(crossinline supplier: () -> Set<T>): Set<T> {
|
||||
override fun containsAll(elements: Collection<T>): Boolean = supplier().containsAll(elements)
|
||||
override fun isEmpty(): Boolean = supplier().isEmpty()
|
||||
override fun iterator(): Iterator<T> = supplier().iterator()
|
||||
override fun toString(): String = supplier().toString()
|
||||
override fun hashCode(): Int = supplier().hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,6 +278,8 @@ internal inline fun <T> dynamicMutableList(crossinline supplier: () -> MutableLi
|
||||
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)
|
||||
override fun toString(): String = supplier().toString()
|
||||
override fun hashCode(): Int = supplier().hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@ -256,6 +297,8 @@ internal inline fun <T> dynamicMutableSet(crossinline supplier: () -> MutableSet
|
||||
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)
|
||||
override fun toString(): String = supplier().toString()
|
||||
override fun hashCode(): Int = supplier().hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,6 +316,8 @@ internal inline fun <K, V> MutableMap<K, V>.observable(crossinline onChanged: ()
|
||||
override fun put(key: K, value: V): V? = this@observable.put(key, value).also { onChanged() }
|
||||
override fun putAll(from: Map<out K, V>) = this@observable.putAll(from).also { onChanged() }
|
||||
override fun remove(key: K): V? = this@observable.remove(key).also { onChanged() }
|
||||
override fun toString(): String = this@observable.toString()
|
||||
override fun hashCode(): Int = this@observable.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,6 +334,8 @@ internal inline fun <T> MutableList<T>.observable(crossinline onChanged: () -> U
|
||||
override fun hasNext(): Boolean = delegate.hasNext()
|
||||
override fun next(): T = delegate.next()
|
||||
override fun remove() = delegate.remove().also { onChanged() }
|
||||
override fun toString(): String = delegate.toString()
|
||||
override fun hashCode(): Int = delegate.hashCode()
|
||||
}
|
||||
|
||||
override fun lastIndexOf(element: T): Int = this@observable.lastIndexOf(element)
|
||||
@ -310,6 +357,8 @@ internal inline fun <T> MutableList<T>.observable(crossinline onChanged: () -> U
|
||||
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 toString(): String = delegate.toString()
|
||||
override fun hashCode(): Int = delegate.hashCode()
|
||||
}
|
||||
|
||||
override fun listIterator(index: Int): MutableListIterator<T> = object : MutableListIterator<T> {
|
||||
@ -323,6 +372,8 @@ internal inline fun <T> MutableList<T>.observable(crossinline onChanged: () -> U
|
||||
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 toString(): String = delegate.toString()
|
||||
override fun hashCode(): Int = delegate.hashCode()
|
||||
}
|
||||
|
||||
override fun remove(element: T): Boolean = this@observable.remove(element).also { onChanged() }
|
||||
@ -335,6 +386,8 @@ internal inline fun <T> MutableList<T>.observable(crossinline onChanged: () -> U
|
||||
|
||||
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)
|
||||
override fun toString(): String = this@observable.toString()
|
||||
override fun hashCode(): Int = this@observable.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@ -349,6 +402,8 @@ internal inline fun <T> MutableCollection<T>.observable(crossinline onChanged: (
|
||||
override fun hasNext(): Boolean = delegate.hasNext()
|
||||
override fun next(): T = delegate.next()
|
||||
override fun remove() = delegate.remove().also { onChanged() }
|
||||
override fun toString(): String = delegate.toString()
|
||||
override fun hashCode(): Int = delegate.hashCode()
|
||||
}
|
||||
|
||||
override fun add(element: T): Boolean = this@observable.add(element).also { onChanged() }
|
||||
@ -360,6 +415,9 @@ internal inline fun <T> MutableCollection<T>.observable(crossinline onChanged: (
|
||||
|
||||
override fun retainAll(elements: Collection<T>): Boolean =
|
||||
this@observable.retainAll(elements).also { onChanged() }
|
||||
|
||||
override fun toString(): String = this@observable.toString()
|
||||
override fun hashCode(): Int = this@observable.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@ -374,6 +432,8 @@ internal inline fun <T> MutableSet<T>.observable(crossinline onChanged: () -> Un
|
||||
override fun hasNext(): Boolean = delegate.hasNext()
|
||||
override fun next(): T = delegate.next()
|
||||
override fun remove() = delegate.remove().also { onChanged() }
|
||||
override fun toString(): String = delegate.toString()
|
||||
override fun hashCode(): Int = delegate.hashCode()
|
||||
}
|
||||
|
||||
override fun add(element: T): Boolean = this@observable.add(element).also { onChanged() }
|
||||
@ -385,6 +445,9 @@ internal inline fun <T> MutableSet<T>.observable(crossinline onChanged: () -> Un
|
||||
|
||||
override fun retainAll(elements: Collection<T>): Boolean =
|
||||
this@observable.retainAll(elements).also { onChanged() }
|
||||
|
||||
override fun toString(): String = this@observable.toString()
|
||||
override fun hashCode(): Int = this@observable.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,8 @@ import kotlin.reflect.full.findAnnotation
|
||||
|
||||
internal val KProperty<*>.serialNameOrPropertyName: String get() = this.findAnnotation<SerialName>()?.value ?: this.name
|
||||
|
||||
internal fun Int.isOdd() = this and 0b1 != 0
|
||||
|
||||
internal inline fun <E> KSerializer<E>.bind(
|
||||
crossinline setter: (E) -> Unit,
|
||||
crossinline getter: () -> E
|
||||
|
@ -9,21 +9,121 @@
|
||||
|
||||
package net.mamoe.mirai.console.setting
|
||||
|
||||
import net.mamoe.yamlkt.Yaml
|
||||
import kotlinx.serialization.UnstableDefault
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonConfiguration
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertSame
|
||||
|
||||
internal class SettingTest {
|
||||
|
||||
class MySetting : Setting() {
|
||||
val int by value(1)
|
||||
var int by value(1)
|
||||
val map by valueReified(mapOf("" to ""))
|
||||
val map2 by valueReified(mapOf("" to mapOf("" to mapOf("" to ""))))
|
||||
val map2 by valueReified(mutableMapOf("" to mutableMapOf("" to "")))
|
||||
}
|
||||
|
||||
@OptIn(UnstableDefault::class)
|
||||
private val jsonPrettyPrint = Json(JsonConfiguration(prettyPrint = true))
|
||||
private val json = Json(JsonConfiguration.Stable)
|
||||
|
||||
@Test
|
||||
fun testStringify() {
|
||||
val setting = MySetting()
|
||||
|
||||
var string = json.stringify(setting.updaterSerializer, Unit)
|
||||
assertEquals("""{"int":1,"map":{},"map2":{}}""", string)
|
||||
|
||||
setting.int = 2
|
||||
|
||||
string = json.stringify(setting.updaterSerializer, Unit)
|
||||
assertEquals("""{"int":2,"map":{},"map2":{}}""", string)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPrimitive() {
|
||||
fun testParseUpdate() {
|
||||
val setting = MySetting()
|
||||
val string = Yaml.nonStrict.stringify(setting.updaterSerializer, Unit)
|
||||
println(string)
|
||||
|
||||
assertEquals(1, setting.int)
|
||||
|
||||
json.parse(
|
||||
setting.updaterSerializer, """
|
||||
{"int":3,"map":{},"map2":{}}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
assertEquals(3, setting.int)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNestedParseUpdate() {
|
||||
val setting = MySetting()
|
||||
|
||||
fun delegation() = setting.map
|
||||
|
||||
val refBefore = setting.map
|
||||
fun reference() = refBefore
|
||||
|
||||
assertEquals(mapOf(), delegation()) // delegation
|
||||
|
||||
json.parse(
|
||||
setting.updaterSerializer, """
|
||||
{"int":1,"map":{"t":"test"},"map2":{}}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
assertEquals(mapOf("t" to "test").toString(), delegation().toString())
|
||||
assertEquals(mapOf("t" to "test").toString(), reference().toString())
|
||||
|
||||
assertSame(reference(), delegation()) // check shadowing
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDeepNestedParseUpdate() {
|
||||
val setting = MySetting()
|
||||
|
||||
fun delegation() = setting.map2
|
||||
|
||||
val refBefore = setting.map2
|
||||
fun reference() = refBefore
|
||||
|
||||
assertEquals(mutableMapOf(), delegation()) // delegation
|
||||
|
||||
json.parse(
|
||||
setting.updaterSerializer, """
|
||||
{"int":1,"map":{},"map2":{"t":{"f":"test"}}}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
assertEquals(mapOf("t" to mapOf("f" to "test")).toString(), delegation().toString())
|
||||
assertEquals(mapOf("t" to mapOf("f" to "test")).toString(), reference().toString())
|
||||
|
||||
assertSame(reference(), delegation()) // check shadowing
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDeepNestedTrackingParseUpdate() {
|
||||
val setting = MySetting()
|
||||
|
||||
setting.map2["t"] = mutableMapOf()
|
||||
|
||||
fun delegation() = setting.map2["t"]!!
|
||||
|
||||
val refBefore = setting.map2["t"]!!
|
||||
fun reference() = refBefore
|
||||
|
||||
assertEquals(mutableMapOf(), delegation()) // delegation
|
||||
|
||||
json.parse(
|
||||
setting.updaterSerializer, """
|
||||
{"int":1,"map":{},"map2":{"t":{"f":"test"}}}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
assertEquals(mapOf("f" to "test").toString(), delegation().toString())
|
||||
assertEquals(mapOf("f" to "test").toString(), reference().toString())
|
||||
|
||||
assertSame(reference(), delegation()) // check shadowing
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user