core/services/posts/common/src/commonMain/kotlin/dev/inmo/postssystem/services/posts/common/BinaryContentSerializer.kt

59 lines
2.6 KiB
Kotlin

package dev.inmo.postssystem.services.posts.common
import dev.inmo.micro_utils.common.FileName
import dev.inmo.micro_utils.mime_types.MimeType
import dev.inmo.micro_utils.mime_types.MimeTypeSerializer
import dev.inmo.postssystem.features.common.common.SimpleInputProvider
import dev.inmo.postssystem.features.content.common.BinaryContent
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlin.reflect.KClass
@Serializer(BinaryContent::class)
class BinaryContentSerializer<T: SimpleInputProvider>(
private val kClass: KClass<T>,
private val serializer: KSerializer<T>
) : KSerializer<BinaryContent> {
@OptIn(InternalSerializationApi::class, ExperimentalSerializationApi::class)
override val descriptor: SerialDescriptor = buildSerialDescriptor(
"BinaryContent",
SerialKind.CONTEXTUAL
) {
element("filename", FileName.serializer().descriptor)
element("mimetype", MimeTypeSerializer.descriptor)
element("data", serializer.descriptor)
}
override fun deserialize(decoder: Decoder): BinaryContent {
return decoder.decodeStructure(descriptor) {
var fileName: FileName? = null
var mimeType: MimeType? = null
var data: T? = null
while (true) {
when (val index = decodeElementIndex(descriptor)) {
0 -> fileName = decodeSerializableElement(descriptor, 0, FileName.serializer())
1 -> mimeType = decodeSerializableElement(descriptor, 1, MimeTypeSerializer)
2 -> data = decodeSerializableElement(descriptor, 2, serializer)
CompositeDecoder.DECODE_DONE -> break
else -> error("Unexpected index: $index")
}
}
BinaryContent(
fileName ?: error("Filename must be presented, but was absent"),
mimeType ?: error("Mimetype must be presented, but was absent"),
data ?: error("Data must be presented, but was absent")
)
}
}
override fun serialize(encoder: Encoder, value: BinaryContent) {
require(kClass.isInstance(value.inputProvider)) { "${value.inputProvider} do not inherit $kClass" }
encoder.encodeStructure(descriptor) {
encodeSerializableElement(descriptor, 0, FileName.serializer(), value.filename)
encodeSerializableElement(descriptor, 1, MimeTypeSerializer, value.mimeType)
encodeSerializableElement(descriptor, 2, serializer, value.inputProvider as T)
}
}
}