diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/serialization/MetaSerializer.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/serialization/MetaSerializer.kt index 2f6a00de..271f95e2 100644 --- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/serialization/MetaSerializer.kt +++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/serialization/MetaSerializer.kt @@ -14,12 +14,12 @@ import kotlinx.serialization.json.JsonOutput @Serializer(Value::class) object ValueSerializer : KSerializer { private val valueTypeSerializer = EnumSerializer(ValueType::class) - private val listSerializer by lazy { ArrayListSerializer(ValueSerializer)} + private val listSerializer by lazy { ArrayListSerializer(ValueSerializer) } override val descriptor: SerialDescriptor = descriptor("Value") { - element("isList") - element("valueType") - element("value") + boolean("isList") + enum("valueType") + element("value", PolymorphicClassDescriptor) } private fun Decoder.decodeValue(): Value { @@ -68,10 +68,11 @@ object ValueSerializer : KSerializer { @Serializer(MetaItem::class) object MetaItemSerializer : KSerializer> { override val descriptor: SerialDescriptor = descriptor("MetaItem") { - element("isNode") - element("value") + boolean("isNode") + element("value", PolymorphicClassDescriptor) } + override fun deserialize(decoder: Decoder): MetaItem<*> { val isNode = decoder.decodeBoolean() return if (isNode) { diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/serialization/serializationUtils.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/serialization/serializationUtils.kt index f83b2197..4d33fad9 100644 --- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/serialization/serializationUtils.kt +++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/serialization/serializationUtils.kt @@ -4,19 +4,64 @@ import kotlinx.serialization.CompositeDecoder import kotlinx.serialization.Decoder import kotlinx.serialization.KSerializer import kotlinx.serialization.SerialDescriptor -import kotlinx.serialization.internal.SerialClassDescImpl +import kotlinx.serialization.internal.* +/** + * A convenience builder for serial descriptors + */ inline class SerialDescriptorBuilder(private val impl: SerialClassDescImpl) { - fun element(name: String, isOptional: Boolean = false) = impl.addElement(name, isOptional) + fun element( + name: String, + descriptor: SerialDescriptor, + isOptional: Boolean = false, + vararg annotations: Annotation + ) { + impl.addElement(name, isOptional) + impl.pushDescriptor(descriptor) + annotations.forEach { + impl.pushAnnotation(it) + } + } - fun annotation(a: Annotation) = impl.pushAnnotation(a) + fun element( + name: String, + isOptional: Boolean = false, + vararg annotations: Annotation, + block: SerialDescriptorBuilder.() -> Unit + ) { + impl.addElement(name, isOptional) + impl.pushDescriptor(SerialDescriptorBuilder(SerialClassDescImpl(name)).apply(block).build()) + annotations.forEach { + impl.pushAnnotation(it) + } + } + + fun boolean(name: String, isOptional: Boolean = false, vararg annotations: Annotation) = + element(name, BooleanDescriptor, isOptional, *annotations) + + fun string(name: String, isOptional: Boolean = false, vararg annotations: Annotation) = + element(name, StringDescriptor, isOptional, *annotations) + + fun int(name: String, isOptional: Boolean = false, vararg annotations: Annotation) = + element(name, IntDescriptor, isOptional, *annotations) + + fun double(name: String, isOptional: Boolean = false, vararg annotations: Annotation) = + element(name, DoubleDescriptor, isOptional, *annotations) + + fun float(name: String, isOptional: Boolean = false, vararg annotations: Annotation) = + element(name, FloatDescriptor, isOptional, *annotations) + + fun long(name: String, isOptional: Boolean = false, vararg annotations: Annotation) = + element(name, LongDescriptor, isOptional, *annotations) + + fun doubleArray(name: String, isOptional: Boolean = false, vararg annotations: Annotation) = + element(name, DoubleArraySerializer.descriptor, isOptional, *annotations) + + inline fun > enum(name: String, isOptional: Boolean = false, vararg annotations: Annotation) = + element(name, EnumSerializer(E::class).descriptor, isOptional, *annotations) fun classAnnotation(a: Annotation) = impl.pushClassAnnotation(a) - fun descriptor(name: String, block: SerialDescriptorBuilder.() -> Unit) = impl.pushDescriptor( - SerialDescriptorBuilder(SerialClassDescImpl(name)).apply(block).build() - ) - fun build(): SerialDescriptor = impl } diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt index ba0ed7c7..f33ad894 100644 --- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt +++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt @@ -51,4 +51,9 @@ class MetaSerializerTest { val restored = Json.plain.parse(NameSerializer, string) assertEquals(restored, name) } + + @Test + fun testMetaItemDescriptor(){ + val descriptor = MetaItemSerializer.descriptor.getElementDescriptor(0) + } } \ No newline at end of file