Serialization.kt 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /*
  2. * Copyright 2020 Mamoe Technologies and contributors.
  3. *
  4. * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
  5. * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
  6. *
  7. * https://github.com/mamoe/mirai/blob/master/LICENSE
  8. */
  9. @file:JvmName("SerializationKt_common")
  10. package net.mamoe.mirai.utils
  11. import kotlinx.serialization.*
  12. import kotlinx.serialization.descriptors.*
  13. import kotlinx.serialization.encoding.Decoder
  14. import kotlinx.serialization.encoding.Encoder
  15. import kotlin.jvm.JvmName
  16. public fun SerialDescriptor.copy(newName: String): SerialDescriptor =
  17. buildClassSerialDescriptor(newName) { takeElementsFrom(this@copy) }
  18. @OptIn(ExperimentalSerializationApi::class) // bad but there is no other solution
  19. public fun ClassSerialDescriptorBuilder.takeElementsFrom(descriptor: SerialDescriptor) {
  20. with(descriptor) {
  21. repeat(descriptor.elementsCount) { index ->
  22. element(
  23. elementName = getElementName(index),
  24. descriptor = getElementDescriptor(index),
  25. annotations = getElementAnnotations(index),
  26. isOptional = isElementOptional(index),
  27. )
  28. }
  29. }
  30. }
  31. public inline fun <T, R> KSerializer<T>.map(
  32. resultantDescriptor: SerialDescriptor,
  33. crossinline deserialize: T.(T) -> R,
  34. crossinline serialize: R.(R) -> T,
  35. ): KSerializer<R> {
  36. return object : KSerializer<R> {
  37. override val descriptor: SerialDescriptor get() = resultantDescriptor
  38. override fun deserialize(decoder: Decoder): R = this@map.deserialize(decoder).let { deserialize(it, it) }
  39. override fun serialize(encoder: Encoder, value: R) = serialize(encoder, value.let { serialize(it, it) })
  40. }
  41. }
  42. @OptIn(ExperimentalSerializationApi::class)
  43. public inline fun <T, R> KSerializer<T>.mapPrimitive(
  44. serialName: String,
  45. crossinline deserialize: (T) -> R,
  46. crossinline serialize: R.(R) -> T,
  47. ): KSerializer<R> {
  48. val kind = this@mapPrimitive.descriptor.kind
  49. check(kind is PrimitiveKind) { "kind must be PrimitiveKind but found $kind" }
  50. return object : KSerializer<R> {
  51. override fun deserialize(decoder: Decoder): R =
  52. this@mapPrimitive.deserialize(decoder).let(deserialize)
  53. override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(serialName, kind)
  54. override fun serialize(encoder: Encoder, value: R) =
  55. this@mapPrimitive.serialize(encoder, value.let { serialize(it, it) })
  56. }
  57. }
  58. public fun <T> MiraiFile.loadNotBlankAs(
  59. serializer: DeserializationStrategy<T>,
  60. stringFormat: StringFormat,
  61. ): T? {
  62. if (!this.exists() || this.length == 0L) {
  63. return null
  64. }
  65. return try {
  66. stringFormat.decodeFromString(serializer, this.readText())
  67. } catch (e: Throwable) { //broken file
  68. e.printStackTrace()
  69. null
  70. }
  71. }
  72. public fun <T> MiraiFile.loadNotBlankAs(
  73. serializer: DeserializationStrategy<T>,
  74. binaryFormat: BinaryFormat,
  75. ): T? {
  76. if (!this.exists() || this.length == 0L) {
  77. return null
  78. }
  79. return try {
  80. binaryFormat.decodeFromByteArray(serializer, this.readBytes())
  81. } catch (e: Throwable) { //broken file
  82. e.printStackTrace()
  83. null
  84. }
  85. }