Przeglądaj źródła

在 Image 序列化时支持全部属性 (#2036)

* fix: Image Serializer Delegate

* use: api dump

* add: test Image serialization

* fix: type (SerialName) and deserialize

* fix: native test
cssxsh 3 lat temu
rodzic
commit
c38740ce2f

+ 13 - 0
mirai-core-api/compatibility-validation/android/api/android.api

@@ -4547,9 +4547,22 @@ public final class net/mamoe/mirai/message/data/ImageType : java/lang/Enum {
 	public static fun values ()[Lnet/mamoe/mirai/message/data/ImageType;
 }
 
+public final class net/mamoe/mirai/message/data/ImageType$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
+	public static final field INSTANCE Lnet/mamoe/mirai/message/data/ImageType$$serializer;
+	public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lnet/mamoe/mirai/message/data/ImageType;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/data/ImageType;)V
+	public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
+}
+
 public final class net/mamoe/mirai/message/data/ImageType$Companion {
 	public final fun match (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/ImageType;
 	public final fun matchOrNull (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/ImageType;
+	public final fun serializer ()Lkotlinx/serialization/KSerializer;
 }
 
 public final class net/mamoe/mirai/message/data/LightApp : net/mamoe/mirai/message/code/CodableMessage, net/mamoe/mirai/message/data/RichMessage {

+ 13 - 0
mirai-core-api/compatibility-validation/jvm/api/jvm.api

@@ -4547,9 +4547,22 @@ public final class net/mamoe/mirai/message/data/ImageType : java/lang/Enum {
 	public static fun values ()[Lnet/mamoe/mirai/message/data/ImageType;
 }
 
+public final class net/mamoe/mirai/message/data/ImageType$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
+	public static final field INSTANCE Lnet/mamoe/mirai/message/data/ImageType$$serializer;
+	public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
+	public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
+	public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lnet/mamoe/mirai/message/data/ImageType;
+	public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
+	public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
+	public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/data/ImageType;)V
+	public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
+}
+
 public final class net/mamoe/mirai/message/data/ImageType$Companion {
 	public final fun match (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/ImageType;
 	public final fun matchOrNull (Ljava/lang/String;)Lnet/mamoe/mirai/message/data/ImageType;
+	public final fun serializer ()Lkotlinx/serialization/KSerializer;
 }
 
 public final class net/mamoe/mirai/message/data/LightApp : net/mamoe/mirai/message/code/CodableMessage, net/mamoe/mirai/message/data/RichMessage {

+ 51 - 7
mirai-core-api/src/commonMain/kotlin/message/data/Image.kt

@@ -25,6 +25,7 @@ import kotlinx.serialization.Serializable
 import kotlinx.serialization.builtins.serializer
 import kotlinx.serialization.descriptors.SerialDescriptor
 import kotlinx.serialization.descriptors.buildClassSerialDescriptor
+import kotlinx.serialization.encoding.CompositeDecoder
 import kotlinx.serialization.encoding.Decoder
 import kotlinx.serialization.encoding.Encoder
 import kotlinx.serialization.encoding.decodeStructure
@@ -200,6 +201,11 @@ public interface Image : Message, MessageContent, CodableMessage {
     public open class FallbackSerializer(serialName: String) : KSerializer<Image> {
         override val descriptor: SerialDescriptor = buildClassSerialDescriptor(serialName) {
             element("imageId", String.serializer().descriptor)
+            element("size", Long.serializer().descriptor)
+            element("imageType", ImageType.serializer().descriptor)
+            element("width", Int.serializer().descriptor)
+            element("height", Int.serializer().descriptor)
+            element("isEmoji", Boolean.serializer().descriptor)
         }
 
         // Note: Manually written to overcome discriminator issues.
@@ -208,24 +214,61 @@ public interface Image : Message, MessageContent, CodableMessage {
             decoder.decodeStructure(descriptor) {
                 if (this.decodeSequentially()) {
                     val imageId = this.decodeStringElement(descriptor, 0)
-                    return Image(imageId)
+                    val size = this.decodeLongElement(descriptor, 1)
+                    val type = this.decodeSerializableElement(descriptor, 2, ImageType.serializer())
+                    val width = this.decodeIntElement(descriptor, 3)
+                    val height = this.decodeIntElement(descriptor, 4)
+                    val isEmoji = this.decodeBooleanElement(descriptor, 5)
+                    return Image(imageId) {
+                        this.size = size
+                        this.type = type
+                        this.width = width
+                        this.height = height
+                        this.isEmoji = isEmoji
+                    }
                 } else {
-                    val index = this.decodeElementIndex(descriptor)
-                    check(index == 0)
-                    val imageId = this.decodeStringElement(descriptor, index)
-                    return Image(imageId)
+                    return Image("") {
+                        while (true) {
+                            when (val index = this@decodeStructure.decodeElementIndex(descriptor)) {
+                                0 -> imageId = this@decodeStructure.decodeStringElement(descriptor, index)
+                                1 -> size = this@decodeStructure.decodeLongElement(descriptor, index)
+                                2 -> type = this@decodeStructure.decodeSerializableElement(
+                                    descriptor,
+                                    index,
+                                    ImageType.serializer()
+                                )
+                                3 -> width = this@decodeStructure.decodeIntElement(descriptor, index)
+                                4 -> height = this@decodeStructure.decodeIntElement(descriptor, index)
+                                5 -> isEmoji = this@decodeStructure.decodeBooleanElement(descriptor, index)
+                                CompositeDecoder.DECODE_DONE -> break
+                            }
+                        }
+                        check(imageId.isNotEmpty()) { "imageId must not empty" }
+                    }
                 }
             }
         }
 
         override fun serialize(encoder: Encoder, value: Image) {
-            Delegate.serializer().serialize(encoder, Delegate(value.imageId))
+            Delegate.serializer().serialize(encoder, Delegate(
+                value.imageId,
+                value.size,
+                value.imageType,
+                value.width,
+                value.height,
+                value.isEmoji
+            ))
         }
 
         @SerialName(SERIAL_NAME)
         @Serializable
         private data class Delegate(
-            val imageId: String
+            val imageId: String,
+            val size: Long,
+            val imageType: ImageType,
+            val width: Int,
+            val height: Int,
+            val isEmoji: Boolean
         )
     }
 
@@ -446,6 +489,7 @@ public inline fun Image(imageId: String): Image = Builder.newBuilder(imageId).bu
 public inline fun Image(imageId: String, builderAction: Builder.() -> Unit = {}): Image =
     Builder.newBuilder(imageId).apply(builderAction).build()
 
+@Serializable
 public enum class ImageType(
     /**
      * @since 2.9.0

+ 40 - 0
mirai-core/src/commonTest/kotlin/message/data/MessageSerializationTest.kt

@@ -124,6 +124,46 @@ internal class MessageSerializationTest : AbstractTest() {
         assertEquals(w, w.serialize(W.serializer()).deserialize(W.serializer()))
     }
 
+    @Test
+    fun `test Image serialization`() {
+        val string = image.serialize()
+        val element = string.deserialize<JsonElement>()
+        element as JsonObject
+        assertEquals(string.deserialize(), image)
+
+        val image2 = Image(image.imageId) {
+            type = ImageType.GIF
+            width = 123
+            height = 456
+        }
+        val string2 = image2.serialize()
+        val element2 = string2.deserialize<JsonElement>()
+        element2 as JsonObject
+        assertEquals(element2["imageType"]?.jsonPrimitive?.content, image2.imageType.name)
+        assertEquals(element2["width"]?.jsonPrimitive?.int, image2.width)
+        assertEquals(element2["height"]?.jsonPrimitive?.int, image2.height)
+        val decoded: Image = string2.deserialize()
+        decoded as Image
+        assertEquals(decoded.imageId, image2.imageId)
+        assertEquals(decoded.imageType, image2.imageType)
+        assertEquals(decoded.width, image2.width)
+        assertEquals(decoded.height, image2.height)
+
+        val string3 = """
+        {
+            "imageType": "GIF",
+            "width": 123,
+            "height": 456,
+            "imageId": "${image.imageId}"
+         }
+        """.trimIndent()
+        val decoded2: Image = string3.deserialize()
+        assertEquals(decoded2.imageId, image2.imageId)
+        assertEquals(decoded2.imageType, image2.imageType)
+        assertEquals(decoded2.width, image2.width)
+        assertEquals(decoded2.height, image2.height)
+    }
+
     @Serializable
     data class RichWrapper(
         val richMessage: RichMessage