diff --git a/mirai-core-api/compatibility-validation/android/api/android.api b/mirai-core-api/compatibility-validation/android/api/android.api index fa1dfa655..2e2f2ab08 100644 --- a/mirai-core-api/compatibility-validation/android/api/android.api +++ b/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 { diff --git a/mirai-core-api/compatibility-validation/jvm/api/jvm.api b/mirai-core-api/compatibility-validation/jvm/api/jvm.api index 2acb48925..bef148cda 100644 --- a/mirai-core-api/compatibility-validation/jvm/api/jvm.api +++ b/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 { diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt b/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt index d2b15423f..50064fa70 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt +++ b/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 { 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 diff --git a/mirai-core/src/commonTest/kotlin/message/data/MessageSerializationTest.kt b/mirai-core/src/commonTest/kotlin/message/data/MessageSerializationTest.kt index 8656cf41e..22f468b5d 100644 --- a/mirai-core/src/commonTest/kotlin/message/data/MessageSerializationTest.kt +++ b/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() + 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() + 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