New Meta serializer
This commit is contained in:
parent
810f79b9ed
commit
acfb070938
@ -27,6 +27,7 @@ class MetaSerializerTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testMetaSerialization() {
|
fun testMetaSerialization() {
|
||||||
val string = JSON_PRETTY.encodeToString(MetaSerializer, meta)
|
val string = JSON_PRETTY.encodeToString(MetaSerializer, meta)
|
||||||
|
println(string)
|
||||||
val restored = JSON_PLAIN.decodeFromString(MetaSerializer, string)
|
val restored = JSON_PLAIN.decodeFromString(MetaSerializer, string)
|
||||||
assertEquals(meta, restored)
|
assertEquals(meta, restored)
|
||||||
}
|
}
|
||||||
@ -35,7 +36,7 @@ class MetaSerializerTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testCborSerialization() {
|
fun testCborSerialization() {
|
||||||
val bytes = Cbor.encodeToByteArray(MetaSerializer, meta)
|
val bytes = Cbor.encodeToByteArray(MetaSerializer, meta)
|
||||||
println(bytes.contentToString())
|
println(bytes.decodeToString())
|
||||||
val restored = Cbor.decodeFromByteArray(MetaSerializer, bytes)
|
val restored = Cbor.decodeFromByteArray(MetaSerializer, bytes)
|
||||||
assertEquals(meta, restored)
|
assertEquals(meta, restored)
|
||||||
}
|
}
|
||||||
|
@ -28,8 +28,8 @@ public interface ObservableMeta : Meta {
|
|||||||
/**
|
/**
|
||||||
* Mutable meta representing object state
|
* Mutable meta representing object state
|
||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable(Config.Companion::class)
|
||||||
public class Config : AbstractMutableMeta<Config>(), ObservableMeta {
|
public class Config() : AbstractMutableMeta<Config>(), ObservableMeta {
|
||||||
|
|
||||||
private val listeners = HashSet<MetaListener>()
|
private val listeners = HashSet<MetaListener>()
|
||||||
|
|
||||||
|
@ -4,14 +4,11 @@ import hep.dataforge.meta.Meta.Companion.VALUE_KEY
|
|||||||
import hep.dataforge.meta.MetaItem.NodeItem
|
import hep.dataforge.meta.MetaItem.NodeItem
|
||||||
import hep.dataforge.meta.MetaItem.ValueItem
|
import hep.dataforge.meta.MetaItem.ValueItem
|
||||||
import hep.dataforge.names.*
|
import hep.dataforge.names.*
|
||||||
import hep.dataforge.values.*
|
import hep.dataforge.values.EnumValue
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import hep.dataforge.values.Null
|
||||||
import kotlinx.serialization.KSerializer
|
import hep.dataforge.values.Value
|
||||||
|
import hep.dataforge.values.boolean
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.Serializer
|
|
||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
|
||||||
import kotlinx.serialization.encoding.Decoder
|
|
||||||
import kotlinx.serialization.encoding.Encoder
|
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
|
||||||
@ -20,29 +17,17 @@ import kotlinx.serialization.json.Json
|
|||||||
* * a [ValueItem] (leaf)
|
* * a [ValueItem] (leaf)
|
||||||
* * a [NodeItem] (node)
|
* * a [NodeItem] (node)
|
||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable(MetaItemSerializer::class)
|
||||||
public sealed class MetaItem<out M : Meta> {
|
public sealed class MetaItem<out M : Meta>() {
|
||||||
|
|
||||||
abstract override fun equals(other: Any?): Boolean
|
abstract override fun equals(other: Any?): Boolean
|
||||||
|
|
||||||
abstract override fun hashCode(): Int
|
abstract override fun hashCode(): Int
|
||||||
|
|
||||||
@Serializable
|
@Serializable(MetaItemSerializer::class)
|
||||||
public class ValueItem(public val value: Value) : MetaItem<Nothing>() {
|
public class ValueItem(public val value: Value) : MetaItem<Nothing>() {
|
||||||
override fun toString(): String = value.toString()
|
override fun toString(): String = value.toString()
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
|
||||||
@Serializer(ValueItem::class)
|
|
||||||
public companion object : KSerializer<ValueItem> {
|
|
||||||
override val descriptor: SerialDescriptor get() = ValueSerializer.descriptor
|
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): ValueItem = ValueItem(ValueSerializer.deserialize(decoder))
|
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, value: ValueItem) {
|
|
||||||
ValueSerializer.serialize(encoder, value.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
return this.value == (other as? ValueItem)?.value
|
return this.value == (other as? ValueItem)?.value
|
||||||
}
|
}
|
||||||
@ -52,23 +37,11 @@ public sealed class MetaItem<out M : Meta> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable(MetaItemSerializer::class)
|
||||||
public class NodeItem<M : Meta>(@Serializable(MetaSerializer::class) public val node: M) : MetaItem<M>() {
|
public class NodeItem<M : Meta>(public val node: M) : MetaItem<M>() {
|
||||||
//Fixing serializer for node could cause class cast problems, but it should not since Meta descendants are not serializeable
|
//Fixing serializer for node could cause class cast problems, but it should not since Meta descendants are not serializeable
|
||||||
override fun toString(): String = node.toString()
|
override fun toString(): String = node.toString()
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
|
||||||
@Serializer(NodeItem::class)
|
|
||||||
public companion object : KSerializer<NodeItem<out Meta>> {
|
|
||||||
override val descriptor: SerialDescriptor get() = MetaSerializer.descriptor
|
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): NodeItem<*> = NodeItem(MetaSerializer.deserialize(decoder))
|
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, value: NodeItem<*>) {
|
|
||||||
MetaSerializer.serialize(encoder, value.node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean = node == (other as? NodeItem<*>)?.node
|
override fun equals(other: Any?): Boolean = node == (other as? NodeItem<*>)?.node
|
||||||
|
|
||||||
override fun hashCode(): Int = node.hashCode()
|
override fun hashCode(): Int = node.hashCode()
|
||||||
@ -112,7 +85,6 @@ public fun interface ItemProvider {
|
|||||||
*
|
*
|
||||||
* * Same name siblings are supported via elements with the same [Name] but different queries
|
* * Same name siblings are supported via elements with the same [Name] but different queries
|
||||||
*/
|
*/
|
||||||
@Serializable(MetaSerializer::class)
|
|
||||||
public interface Meta : MetaRepr, ItemProvider {
|
public interface Meta : MetaRepr, ItemProvider {
|
||||||
/**
|
/**
|
||||||
* Top level items of meta tree
|
* Top level items of meta tree
|
||||||
|
@ -1,17 +1,54 @@
|
|||||||
package hep.dataforge.meta
|
package hep.dataforge.meta
|
||||||
|
|
||||||
import hep.dataforge.names.NameToken
|
import hep.dataforge.names.NameToken
|
||||||
|
import hep.dataforge.values.ValueSerializer
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.InternalSerializationApi
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.Serializer
|
import kotlinx.serialization.Serializer
|
||||||
import kotlinx.serialization.builtins.MapSerializer
|
import kotlinx.serialization.builtins.MapSerializer
|
||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
import kotlinx.serialization.descriptors.*
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.*
|
||||||
import kotlinx.serialization.encoding.Encoder
|
|
||||||
import kotlinx.serialization.json.JsonDecoder
|
import kotlinx.serialization.json.JsonDecoder
|
||||||
import kotlinx.serialization.json.JsonEncoder
|
import kotlinx.serialization.json.JsonEncoder
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
|
public object MetaItemSerializer : KSerializer<MetaItem<*>> {
|
||||||
|
|
||||||
|
@OptIn(InternalSerializationApi::class)
|
||||||
|
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("hep.dataforge.meta.MetaItem") {
|
||||||
|
element<Boolean>("isNode")
|
||||||
|
element("content", buildSerialDescriptor("MetaItem.content", PolymorphicKind.SEALED))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): MetaItem<*> {
|
||||||
|
decoder.decodeStructure(descriptor) {
|
||||||
|
//Force strict serialization order
|
||||||
|
require(decodeElementIndex(descriptor) == 0) { "Node flag must be first item serialized" }
|
||||||
|
val isNode = decodeBooleanElement(descriptor, 0)
|
||||||
|
require(decodeElementIndex(descriptor) == 1) { "Missing MetaItem content" }
|
||||||
|
val item = if (isNode) {
|
||||||
|
decodeSerializableElement(descriptor,1, MetaSerializer).asMetaItem()
|
||||||
|
} else {
|
||||||
|
decodeSerializableElement(descriptor,1,ValueSerializer).asMetaItem()
|
||||||
|
}
|
||||||
|
require(decodeElementIndex(descriptor) == CompositeDecoder.DECODE_DONE){"Serialized MetaItem contains additional fields"}
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, value: MetaItem<*>) {
|
||||||
|
encoder.encodeStructure(descriptor) {
|
||||||
|
encodeBooleanElement(descriptor, 0, value is MetaItem.NodeItem)
|
||||||
|
when (value) {
|
||||||
|
is MetaItem.ValueItem -> encodeSerializableElement(descriptor, 1, ValueSerializer, value.value)
|
||||||
|
is MetaItem.NodeItem -> encodeSerializableElement(descriptor, 1, MetaSerializer, value.node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialized for meta
|
* Serialized for meta
|
||||||
*/
|
*/
|
||||||
@ -19,9 +56,9 @@ import kotlinx.serialization.json.JsonObject
|
|||||||
@Serializer(Meta::class)
|
@Serializer(Meta::class)
|
||||||
public object MetaSerializer : KSerializer<Meta> {
|
public object MetaSerializer : KSerializer<Meta> {
|
||||||
|
|
||||||
private val mapSerializer = MapSerializer(
|
private val mapSerializer: KSerializer<Map<NameToken, MetaItem<Meta>>> = MapSerializer(
|
||||||
NameToken.serializer(),
|
NameToken,
|
||||||
MetaItem.serializer(MetaSerializer)
|
MetaItemSerializer//MetaItem.serializer(MetaSerializer)
|
||||||
)
|
)
|
||||||
|
|
||||||
override val descriptor: SerialDescriptor get() = mapSerializer.descriptor
|
override val descriptor: SerialDescriptor get() = mapSerializer.descriptor
|
||||||
|
@ -19,7 +19,6 @@ public enum class ValueType {
|
|||||||
*
|
*
|
||||||
* Value can represent a list of value objects.
|
* Value can represent a list of value objects.
|
||||||
*/
|
*/
|
||||||
@Serializable(ValueSerializer::class)
|
|
||||||
public interface Value {
|
public interface Value {
|
||||||
/**
|
/**
|
||||||
* Get raw value of this value
|
* Get raw value of this value
|
||||||
|
Loading…
Reference in New Issue
Block a user