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

* fix: Image Serializer Delegate

* use: api dump

* add: test Image serialization

* fix: type (SerialName) and deserialize

* fix: native test
This commit is contained in:
cssxsh 2022-07-22 03:05:08 +08:00 committed by GitHub
parent cd60519b60
commit c38740ce2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 117 additions and 7 deletions

View File

@ -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 {

View File

@ -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 {

View File

@ -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

View File

@ -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