Fix meta serialization

This commit is contained in:
Alexander Nozik 2020-03-15 09:22:08 +03:00
parent db03dfaae9
commit 4ab71a79db
10 changed files with 44 additions and 46 deletions

View File

@ -11,17 +11,17 @@ import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class MetaSerializerTest { class MetaSerializerTest {
val meta = Meta {
"a" put 22
"node" put {
"b" put "DDD"
"c" put 11.1
"array" put doubleArrayOf(1.0, 2.0, 3.0)
}
}
@Test @Test
fun testMetaSerialization() { fun testMetaSerialization() {
val meta = Meta {
"a" put 22
"node" put {
"b" put "DDD"
"c" put 11.1
"array" put doubleArrayOf(1.0, 2.0, 3.0)
}
}
val string = Json.indented.stringify(MetaSerializer, meta) val string = Json.indented.stringify(MetaSerializer, meta)
val restored = Json.plain.parse(MetaSerializer, string) val restored = Json.plain.parse(MetaSerializer, string)
assertEquals(restored, meta) assertEquals(restored, meta)
@ -29,15 +29,6 @@ class MetaSerializerTest {
@Test @Test
fun testCborSerialization() { fun testCborSerialization() {
val meta = Meta {
"a" put 22
"node" put {
"b" put "DDD"
"c" put 11.1
"array" put doubleArrayOf(1.0, 2.0, 3.0)
}
}
val bytes = Cbor.dump(MetaSerializer, meta) val bytes = Cbor.dump(MetaSerializer, meta)
println(bytes.contentToString()) println(bytes.contentToString())
val restored = Cbor.load(MetaSerializer, bytes) val restored = Cbor.load(MetaSerializer, bytes)

View File

@ -1,9 +1,9 @@
package hep.dataforge.io package hep.dataforge.io
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.meta.DFExperimental import hep.dataforge.meta.DFExperimental
import hep.dataforge.meta.EmptyMeta import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.meta.isEmpty import hep.dataforge.meta.isEmpty
import kotlinx.io.* import kotlinx.io.*
import java.nio.file.Files import java.nio.file.Files
@ -14,6 +14,7 @@ import kotlin.streams.asSequence
/** /**
* Resolve IOFormat based on type * Resolve IOFormat based on type
*/ */
@Suppress("UNCHECKED_CAST")
@DFExperimental @DFExperimental
inline fun <reified T : Any> IOPlugin.resolveIOFormat(): IOFormat<T>? { inline fun <reified T : Any> IOPlugin.resolveIOFormat(): IOFormat<T>? {
return ioFormats.values.find { it.type.isSuperclassOf(T::class) } as IOFormat<T>? return ioFormats.values.find { it.type.isSuperclassOf(T::class) } as IOFormat<T>?

View File

@ -3,7 +3,6 @@ package hep.dataforge.io
import hep.dataforge.io.functions.FunctionServer import hep.dataforge.io.functions.FunctionServer
import hep.dataforge.io.functions.function import hep.dataforge.io.functions.function
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.buildMeta
import hep.dataforge.names.Name import hep.dataforge.names.Name
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.full.isSuperclassOf import kotlin.reflect.full.isSuperclassOf
@ -14,7 +13,7 @@ fun IOPlugin.resolveIOFormatName(type: KClass<*>): Name {
?: error("Can't resolve IOFormat for type $type") ?: error("Can't resolve IOFormat for type $type")
} }
inline fun <reified T : Any, reified R : Any> IOPlugin.generateFunctionMeta(functionName: String): Meta = buildMeta { inline fun <reified T : Any, reified R : Any> IOPlugin.generateFunctionMeta(functionName: String): Meta = Meta {
FunctionServer.FUNCTION_NAME_KEY put functionName FunctionServer.FUNCTION_NAME_KEY put functionName
FunctionServer.INPUT_FORMAT_KEY put resolveIOFormatName(T::class).toString() FunctionServer.INPUT_FORMAT_KEY put resolveIOFormatName(T::class).toString()
FunctionServer.OUTPUT_FORMAT_KEY put resolveIOFormatName(R::class).toString() FunctionServer.OUTPUT_FORMAT_KEY put resolveIOFormatName(R::class).toString()

View File

@ -4,6 +4,7 @@ import hep.dataforge.names.Name
import hep.dataforge.names.NameToken import hep.dataforge.names.NameToken
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.plus import hep.dataforge.names.plus
import kotlinx.serialization.*
//TODO add validator to configuration //TODO add validator to configuration
@ -20,6 +21,7 @@ interface ObservableMeta : Meta {
/** /**
* Mutable meta representing object state * Mutable meta representing object state
*/ */
@Serializable
class Config : AbstractMutableMeta<Config>(), ObservableMeta { class Config : AbstractMutableMeta<Config>(), ObservableMeta {
private val listeners = HashSet<MetaListener>() private val listeners = HashSet<MetaListener>()
@ -66,8 +68,19 @@ class Config : AbstractMutableMeta<Config>(), ObservableMeta {
override fun empty(): Config = Config() override fun empty(): Config = Config()
companion object { @Serializer(Config::class)
companion object ConfigSerializer : KSerializer<Config> {
fun empty(): Config = Config() fun empty(): Config = Config()
override val descriptor: SerialDescriptor get() = MetaSerializer.descriptor
override fun deserialize(decoder: Decoder): Config {
return MetaSerializer.deserialize(decoder).asConfig()
}
override fun serialize(encoder: Encoder, value: Config) {
MetaSerializer.serialize(encoder, value)
}
} }
} }

View File

@ -15,6 +15,7 @@ import kotlinx.serialization.*
*/ */
@Serializable @Serializable
sealed class MetaItem<out M : Meta> { sealed class MetaItem<out M : Meta> {
@Serializable @Serializable
data class ValueItem(val value: Value) : MetaItem<Nothing>() { data class ValueItem(val value: Value) : MetaItem<Nothing>() {
override fun toString(): String = value.toString() override fun toString(): String = value.toString()
@ -32,12 +33,13 @@ sealed class MetaItem<out M : Meta> {
} }
@Serializable @Serializable
data class NodeItem<M : Meta>(val node: M) : MetaItem<M>() { data class NodeItem<M : Meta>(@Serializable(MetaSerializer::class) val node: M) : MetaItem<M>() {
//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()
@Serializer(NodeItem::class) @Serializer(NodeItem::class)
companion object : KSerializer<NodeItem<*>> { companion object : KSerializer<NodeItem<out Meta>> {
override val descriptor: SerialDescriptor get() = ValueSerializer.descriptor override val descriptor: SerialDescriptor get() = MetaSerializer.descriptor
override fun deserialize(decoder: Decoder): NodeItem<*> = NodeItem(MetaSerializer.deserialize(decoder)) override fun deserialize(decoder: Decoder): NodeItem<*> = NodeItem(MetaSerializer.deserialize(decoder))
@ -199,8 +201,9 @@ abstract class AbstractMetaNode<M : MetaNode<M>> : MetaNode<M>, MetaBase()
* *
* If the argument is possibly mutable node, it is copied on creation * If the argument is possibly mutable node, it is copied on creation
*/ */
class SealedMeta internal constructor(override val items: Map<NameToken, MetaItem<SealedMeta>>) : class SealedMeta internal constructor(
AbstractMetaNode<SealedMeta>() override val items: Map<NameToken, MetaItem<SealedMeta>>
) : AbstractMetaNode<SealedMeta>()
/** /**
* Generate sealed node from [this]. If it is already sealed return it as is * Generate sealed node from [this]. If it is already sealed return it as is

View File

@ -8,8 +8,6 @@ import kotlinx.serialization.json.JsonObjectSerializer
import kotlinx.serialization.json.JsonOutput import kotlinx.serialization.json.JsonOutput
private class DeserializedMeta(override val items: Map<NameToken, MetaItem<Meta>>) : MetaBase()
/** /**
* Serialized for meta * Serialized for meta
*/ */
@ -26,7 +24,9 @@ object MetaSerializer : KSerializer<Meta> {
return if (decoder is JsonInput) { return if (decoder is JsonInput) {
JsonObjectSerializer.deserialize(decoder).toMeta() JsonObjectSerializer.deserialize(decoder).toMeta()
} else { } else {
DeserializedMeta(mapSerializer.deserialize(decoder)) object : MetaBase() {
override val items: Map<NameToken, MetaItem<*>> = mapSerializer.deserialize(decoder)
}
} }
} }
@ -37,17 +37,4 @@ object MetaSerializer : KSerializer<Meta> {
mapSerializer.serialize(encoder, value.items) mapSerializer.serialize(encoder, value.items)
} }
} }
}
@Serializer(Config::class)
object ConfigSerializer : KSerializer<Config> {
override val descriptor: SerialDescriptor get() = MetaSerializer.descriptor
override fun deserialize(decoder: Decoder): Config {
return MetaSerializer.deserialize(decoder).asConfig()
}
override fun serialize(encoder: Encoder, value: Config) {
MetaSerializer.serialize(encoder, value)
}
} }

View File

@ -168,8 +168,9 @@ fun Configurable.float(default: Float, key: Name? = null): ReadWriteProperty<Any
/** /**
* Enum delegate * Enum delegate
*/ */
inline fun <reified E : Enum<E>> Configurable.enum(default: E, key: Name? = null): ReadWriteProperty<Any?, E> = inline fun <reified E : Enum<E>> Configurable.enum(default: E, key: Name? = null): ReadWriteProperty<Any?, E> {
item(default, key).transform { it.enum<E>() ?: default } return item(default, key).transform { it.enum<E>() ?: default }
}
/* /*
* Extra delegates for special cases * Extra delegates for special cases

Binary file not shown.

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

3
gradlew.bat vendored
View File

@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"