From ff931ed26e0500e13edf7d3ea7302ae7f53377f2 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sun, 24 May 2020 18:56:08 +0800 Subject: [PATCH] Add smart serializers for PluginDescription --- .../plugins/builtin/JvmPluginDescription.kt | 4 +- .../mirai/console/plugins/description.kt | 68 +++++++++++++------ .../console/setting/internal/internal.kt | 11 +++ 3 files changed, 60 insertions(+), 23 deletions(-) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/builtin/JvmPluginDescription.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/builtin/JvmPluginDescription.kt index be5e73810..562ad58f2 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/builtin/JvmPluginDescription.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/builtin/JvmPluginDescription.kt @@ -20,7 +20,7 @@ import java.io.File @Serializable class JvmPluginDescription internal constructor( - override val kind: PluginKind, + override val kind: PluginKind = PluginKind.NORMAL, override val name: String, @SerialName("main") val mainClassName: String, @@ -28,7 +28,7 @@ class JvmPluginDescription internal constructor( override val version: String, override val info: String = "", @SerialName("depends") - override val dependencies: List + override val dependencies: List<@Serializable(with = PluginDependency.SmartSerializer::class) PluginDependency> = listOf() ) : PluginDescription, FilePluginDescription { /** diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/description.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/description.kt index 284025f84..4d23c90e4 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/description.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/description.kt @@ -11,11 +11,14 @@ package net.mamoe.mirai.console.plugins import kotlinx.serialization.* import kotlinx.serialization.builtins.serializer +import net.mamoe.mirai.console.setting.internal.map +import net.mamoe.yamlkt.Yaml +import net.mamoe.yamlkt.YamlDynamicSerializer import java.io.File /** 插件类型 */ -@Serializable(with = PluginKind.Serializer::class) +@Serializable(with = PluginKind.AsStringSerializer::class) enum class PluginKind { /** 表示此插件提供一个 [PluginLoader], 应在加载其他 [NORMAL] 类型插件前加载 */ LOADER, @@ -23,18 +26,14 @@ enum class PluginKind { /** 表示此插件为一个通常的插件, 按照正常的依赖关系加载. */ NORMAL; - companion object Serializer : KSerializer { - override val descriptor: SerialDescriptor get() = String.serializer().descriptor - - override fun deserialize(decoder: Decoder): PluginKind { - val name = String.serializer().deserialize(decoder) - return values().firstOrNull { it.name.equals(name, ignoreCase = true) } ?: NORMAL + object AsStringSerializer : KSerializer by String.serializer().map( + serializer = { it.name }, + deserializer = { str -> + values().firstOrNull { + it.name.equals(str, ignoreCase = true) + } ?: NORMAL } - - override fun serialize(encoder: Encoder, value: PluginKind) { - return String.serializer().serialize(encoder, value.toString()) - } - } + ) } /** @@ -49,7 +48,7 @@ interface PluginDescription { val info: String /** 此插件依赖的其他插件, 将会在这些插件加载之后加载此插件 */ - val dependencies: List + val dependencies: List<@Serializable(with = PluginDependency.SmartSerializer::class) PluginDependency> } /** 插件的一个依赖的信息 */ @@ -58,31 +57,58 @@ data class PluginDependency( /** 依赖插件名 */ val name: String, /** - * 依赖版本号 + * 依赖版本号. 为 null 时则为不限制版本. * @see versionKind 版本号类型 */ - val version: String, + val version: String? = null, /** 版本号类型 */ - val versionKind: VersionKind, + val versionKind: VersionKind = VersionKind.AT_LEAST, /** * 若为 `false`, 插件在找不到此依赖时也能正常加载. */ - val isOptional: Boolean + val isOptional: Boolean = false ) { - enum class VersionKind { + /** 版本号类型 */ + @Serializable(with = VersionKind.AsStringSerializer::class) + enum class VersionKind( + private vararg val serialNames: String + ) { /** 要求依赖精确的版本 */ - EXACT, + EXACT("exact"), /** 要求依赖最低版本 */ - AT_LEAST, + AT_LEAST("at_least", "AtLeast", "least", "lowest", "+"), /** 要求依赖最高版本 */ - AT_MOST + AT_MOST("at_most", "AtMost", "most", "highest", "-"); + + object AsStringSerializer : KSerializer by String.serializer().map( + serializer = { it.serialNames.first() }, + deserializer = { str -> + values().firstOrNull { + it.serialNames.any { name -> name.equals(str, ignoreCase = true) } + } ?: AT_LEAST + } + ) } override fun toString(): String { return "$name ${versionKind.toEnglishString()}v$version" } + + + /** + * 可支持解析 [String] 作为 [PluginDependency.version] 或单个 [PluginDependency] + */ + object SmartSerializer : KSerializer by YamlDynamicSerializer.map( + serializer = { it }, + deserializer = { any -> + when (any) { + is Map<*, *> -> Yaml.nonStrict.parse(serializer(), Yaml.nonStrict.stringify(any)) + else -> PluginDependency(any.toString()) + } + } + ) } /** diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/internal.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/internal.kt index 92d22dd46..ee3e4418b 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/internal.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/setting/internal/internal.kt @@ -164,3 +164,14 @@ internal inline fun KSerializer.bind( this@bind.serialize(encoder, getter()) } } + +internal inline fun KSerializer.map( + crossinline serializer: (R) -> E, + crossinline deserializer: (E) -> R +): KSerializer { + return object : KSerializer { + override val descriptor: SerialDescriptor get() = this@map.descriptor + override fun deserialize(decoder: Decoder): R = this@map.deserialize(decoder).let(deserializer) + override fun serialize(encoder: Encoder, value: R) = this@map.serialize(encoder, value.let(serializer)) + } +}