diff --git a/dataforge-context/build.gradle.kts b/dataforge-context/build.gradle.kts index 104f4037..dd581254 100644 --- a/dataforge-context/build.gradle.kts +++ b/dataforge-context/build.gradle.kts @@ -1,10 +1,12 @@ +import scientifik.coroutines + plugins { id("scientifik.mpp") } description = "Context and provider definitions" -val coroutinesVersion: String = Scientifik.coroutinesVersion +coroutines() kotlin { sourceSets { @@ -13,20 +15,17 @@ kotlin { api(project(":dataforge-meta")) api(kotlin("reflect")) api("io.github.microutils:kotlin-logging-common:1.7.8") - api("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutinesVersion") } } val jvmMain by getting { dependencies { api("io.github.microutils:kotlin-logging:1.7.8") api("ch.qos.logback:logback-classic:1.2.3") - api("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion") } } val jsMain by getting { dependencies { api("io.github.microutils:kotlin-logging-js:1.7.8") - api("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:$coroutinesVersion") } } } diff --git a/dataforge-io/build.gradle.kts b/dataforge-io/build.gradle.kts index 2606f5ea..1760f613 100644 --- a/dataforge-io/build.gradle.kts +++ b/dataforge-io/build.gradle.kts @@ -1,4 +1,5 @@ -import scientifik.useSerialization +import scientifik.DependencySourceSet.TEST +import scientifik.serialization plugins { id("scientifik.mpp") @@ -6,7 +7,9 @@ plugins { description = "IO module" -useSerialization() +serialization(sourceSet = TEST){ + cbor() +} val ioVersion by rootProject.extra("0.2.0-npm-dev-4") @@ -16,17 +19,6 @@ kotlin { dependencies { api(project(":dataforge-context")) api("org.jetbrains.kotlinx:kotlinx-io:$ioVersion") - //api("org.jetbrains.kotlinx:kotlinx-io-metadata:$ioVersion") - } - } - jvmMain { - dependencies { - //api("org.jetbrains.kotlinx:kotlinx-io-jvm:$ioVersion") - } - } - jsMain { - dependencies { - //api("org.jetbrains.kotlinx:kotlinx-io-js:$ioVersion") } } } diff --git a/dataforge-io/dataforge-io-yaml/build.gradle.kts b/dataforge-io/dataforge-io-yaml/build.gradle.kts index bad9b42e..14ea2c19 100644 --- a/dataforge-io/dataforge-io-yaml/build.gradle.kts +++ b/dataforge-io/dataforge-io-yaml/build.gradle.kts @@ -1,4 +1,4 @@ -import scientifik.useSerialization +import scientifik.serialization plugins { id("scientifik.jvm") @@ -6,9 +6,11 @@ plugins { description = "YAML meta IO" -useSerialization() +serialization{ + yaml() +} dependencies { api(project(":dataforge-io")) - api("org.yaml:snakeyaml:1.25") + api("org.yaml:snakeyaml:1.26") } diff --git a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt index be74d080..6361c5dd 100644 --- a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt +++ b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt @@ -21,7 +21,7 @@ class FrontMatterEnvelopeFormat( var line: String = "" var offset = 0u do { - line = readUtf8Line() ?: error("Input does not contain front matter separator") + line = readUtf8Line() //?: error("Input does not contain front matter separator") offset += line.toUtf8Bytes().size.toUInt() } while (!line.startsWith(SEPARATOR)) @@ -46,7 +46,7 @@ class FrontMatterEnvelopeFormat( override fun Input.readObject(): Envelope { var line: String = "" do { - line = readUtf8Line() ?: error("Input does not contain front matter separator") + line = readUtf8Line() //?: error("Input does not contain front matter separator") } while (!line.startsWith(SEPARATOR)) val readMetaFormat = @@ -89,7 +89,7 @@ class FrontMatterEnvelopeFormat( override fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat? { val line = input.readUtf8Line() - return if (line != null && line.startsWith("---")) { + return if (line.startsWith("---")) { invoke() } else { null diff --git a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/YamlMetaFormat.kt b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/YamlMetaFormat.kt index d0543fd0..d1ab09e4 100644 --- a/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/YamlMetaFormat.kt +++ b/dataforge-io/dataforge-io-yaml/src/main/kotlin/hep/dataforge/io/yaml/YamlMetaFormat.kt @@ -1,13 +1,12 @@ package hep.dataforge.io.yaml import hep.dataforge.context.Context -import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.io.MetaFormat import hep.dataforge.io.MetaFormatFactory import hep.dataforge.meta.DFExperimental import hep.dataforge.meta.Meta +import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.meta.toMap -import hep.dataforge.meta.scheme.toMeta import hep.dataforge.meta.toMeta import kotlinx.io.Input import kotlinx.io.Output diff --git a/dataforge-io/dataforge-io-yaml/src/test/kotlin/hep/dataforge/io/yaml/YamlMetaFormatTest.kt b/dataforge-io/dataforge-io-yaml/src/test/kotlin/hep/dataforge/io/yaml/YamlMetaFormatTest.kt index b330e080..24fb6593 100644 --- a/dataforge-io/dataforge-io-yaml/src/test/kotlin/hep/dataforge/io/yaml/YamlMetaFormatTest.kt +++ b/dataforge-io/dataforge-io-yaml/src/test/kotlin/hep/dataforge/io/yaml/YamlMetaFormatTest.kt @@ -3,7 +3,6 @@ package hep.dataforge.io.yaml import hep.dataforge.io.parse import hep.dataforge.io.toString import hep.dataforge.meta.Meta -import hep.dataforge.meta.buildMeta import hep.dataforge.meta.get import hep.dataforge.meta.seal import kotlin.test.Test @@ -13,7 +12,7 @@ import kotlin.test.assertEquals class YamlMetaFormatTest { @Test fun testYamlMetaFormat() { - val meta = buildMeta { + val meta = Meta { "a" put 22 "node" put { "b" put "DDD" diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt index c86fe883..e753b56c 100644 --- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/BinaryMetaFormat.kt @@ -1,8 +1,11 @@ package hep.dataforge.io import hep.dataforge.context.Context +import hep.dataforge.meta.Meta +import hep.dataforge.meta.MetaBuilder +import hep.dataforge.meta.MetaItem import hep.dataforge.meta.descriptors.NodeDescriptor -import hep.dataforge.meta.* +import hep.dataforge.meta.setItem import hep.dataforge.values.* import kotlinx.io.* import kotlinx.io.text.readUtf8String @@ -112,7 +115,7 @@ object BinaryMetaFormat : MetaFormat, MetaFormatFactory { } 'M' -> { val length = readInt() - val meta = buildMeta { + val meta = Meta { (1..length).forEach { _ -> val name = readString() val item = readMetaItem() diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt index 8e0b16de..9541c8fb 100644 --- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt +++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/EnvelopeParts.kt @@ -77,7 +77,7 @@ fun EnvelopeBuilder.multipart( writeRawString(MULTIPART_DATA_SEPARATOR) writeEnvelope(envelope) meta { - append(INDEX_KEY, buildMeta { + append(INDEX_KEY, Meta { "key" put key "index" put counter }) diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt index 1101b35f..01606e6d 100644 --- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/JsonMetaFormat.kt @@ -2,29 +2,20 @@ package hep.dataforge.io + import hep.dataforge.context.Context -import hep.dataforge.meta.descriptors.ItemDescriptor -import hep.dataforge.meta.descriptors.NodeDescriptor -import hep.dataforge.meta.descriptors.ValueDescriptor import hep.dataforge.meta.Meta -import hep.dataforge.meta.MetaBase -import hep.dataforge.meta.MetaItem -import hep.dataforge.meta.serialization.toJson -import hep.dataforge.meta.serialization.toMeta -import hep.dataforge.names.NameToken -import hep.dataforge.names.toName -import hep.dataforge.values.* +import hep.dataforge.meta.descriptors.NodeDescriptor +import hep.dataforge.meta.node +import hep.dataforge.meta.toJson +import hep.dataforge.meta.toMetaItem import kotlinx.io.Input import kotlinx.io.Output import kotlinx.io.text.readUtf8String import kotlinx.io.text.writeUtf8String import kotlinx.serialization.UnstableDefault - - -import kotlinx.serialization.json.* -import kotlin.collections.component1 -import kotlin.collections.component2 -import kotlin.collections.set +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonObjectSerializer @OptIn(UnstableDefault::class) class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat { @@ -37,11 +28,12 @@ class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat { override fun Input.readMeta(descriptor: NodeDescriptor?): Meta { val str = readUtf8String() val jsonElement = json.parseJson(str) - return jsonElement.toMeta() + val item = jsonElement.toMetaItem(descriptor) + return item.node ?: Meta.EMPTY } companion object : MetaFormatFactory { - val DEFAULT_JSON = Json{prettyPrint = true} + val DEFAULT_JSON = Json { prettyPrint = true } override fun invoke(meta: Meta, context: Context): MetaFormat = default diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt index ebeedd6d..7023ce1a 100644 --- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaglessEnvelopeFormat.kt @@ -8,7 +8,6 @@ import kotlinx.io.text.readRawString import kotlinx.io.text.readUtf8Line import kotlinx.io.text.writeRawString import kotlinx.io.text.writeUtf8String -import kotlinx.serialization.toUtf8Bytes @ExperimentalIoApi class TaglessEnvelopeFormat( @@ -155,7 +154,7 @@ class TaglessEnvelopeFormat( } do { - line = readUtf8Line() ?: return PartialEnvelope(Meta.EMPTY, offset.toUInt(), 0.toULong()) + line = readUtf8Line() //?: return PartialEnvelope(Meta.EMPTY, offset.toUInt(), 0.toULong()) offset += line.encodeToByteArray().size.toUInt() //returning an Envelope without data if end of input is reached } while (!line.startsWith(dataStart)) diff --git a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt index 9064a485..6fc801ec 100644 --- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt +++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaFormatTest.kt @@ -20,7 +20,7 @@ fun MetaFormat.fromBytes(packet: Bytes): Meta { class MetaFormatTest { @Test fun testBinaryMetaFormat() { - val meta = buildMeta { + val meta = Meta { "a" put 22 "node" put { "b" put "DDD" @@ -35,7 +35,7 @@ class MetaFormatTest { @Test fun testJsonMetaFormat() { - val meta = buildMeta { + val meta = Meta { "a" put 22 "node" put { "b" put "DDD" 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 37db8833..69b0427b 100644 --- a/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt +++ b/dataforge-io/src/commonTest/kotlin/hep/dataforge/io/MetaSerializerTest.kt @@ -1,9 +1,9 @@ package hep.dataforge.io -import hep.dataforge.io.serialization.MetaItemSerializer -import hep.dataforge.io.serialization.MetaSerializer -import hep.dataforge.io.serialization.NameSerializer -import hep.dataforge.meta.buildMeta +import hep.dataforge.meta.Meta +import hep.dataforge.meta.MetaItem +import hep.dataforge.meta.MetaSerializer +import hep.dataforge.names.Name import hep.dataforge.names.toName import kotlinx.serialization.cbor.Cbor import kotlinx.serialization.json.Json @@ -13,7 +13,7 @@ import kotlin.test.assertEquals class MetaSerializerTest { @Test fun testMetaSerialization() { - val meta = buildMeta { + val meta = Meta { "a" put 22 "node" put { "b" put "DDD" @@ -29,7 +29,7 @@ class MetaSerializerTest { @Test fun testCborSerialization() { - val meta = buildMeta { + val meta = Meta { "a" put 22 "node" put { "b" put "DDD" @@ -47,13 +47,13 @@ class MetaSerializerTest { @Test fun testNameSerialization() { val name = "a.b.c".toName() - val string = Json.indented.stringify(NameSerializer, name) - val restored = Json.plain.parse(NameSerializer, string) + val string = Json.indented.stringify(Name.serializer(), name) + val restored = Json.plain.parse(Name.serializer(), string) assertEquals(restored, name) } @Test - fun testMetaItemDescriptor(){ - val descriptor = MetaItemSerializer.descriptor.getElementDescriptor(0) + fun testMetaItemDescriptor() { + val descriptor = MetaItem.serializer(MetaSerializer).descriptor.getElementDescriptor(0) } } \ No newline at end of file diff --git a/dataforge-meta/build.gradle.kts b/dataforge-meta/build.gradle.kts index f19a39fc..fea7ecd7 100644 --- a/dataforge-meta/build.gradle.kts +++ b/dataforge-meta/build.gradle.kts @@ -1,9 +1,9 @@ -import scientifik.useSerialization +import scientifik.serialization plugins { id("scientifik.mpp") } -useSerialization() +serialization() description = "Meta definition and basic operations on meta" \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serialization/JsonMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt similarity index 90% rename from dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serialization/JsonMeta.kt rename to dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt index 78357c6d..ee906008 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serialization/JsonMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/JsonMeta.kt @@ -1,8 +1,5 @@ -package hep.dataforge.meta.serialization +package hep.dataforge.meta -import hep.dataforge.meta.Meta -import hep.dataforge.meta.MetaBase -import hep.dataforge.meta.MetaItem import hep.dataforge.meta.descriptors.ItemDescriptor import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.meta.descriptors.ValueDescriptor @@ -52,12 +49,7 @@ fun Meta.toJson(descriptor: NodeDescriptor? = null): JsonObject { return JsonObject(map) } -fun JsonElement.toMeta(descriptor: NodeDescriptor? = null): Meta { - return when (val item = toMetaItem(descriptor)) { - is MetaItem.NodeItem<*> -> item.node - is MetaItem.ValueItem -> item.value.toMeta() - } -} +fun JsonObject.toMeta(descriptor: NodeDescriptor? = null): Meta = JsonMeta(this, descriptor) fun JsonPrimitive.toValue(descriptor: ValueDescriptor?): Value { return when (this) { @@ -106,7 +98,12 @@ class JsonMeta(val json: JsonObject, val descriptor: NodeDescriptor? = null) : M this[key] = MetaItem.ValueItem(value.toValue(itemDescriptor as? ValueDescriptor)) as MetaItem } is JsonObject -> { - this[key] = MetaItem.NodeItem(JsonMeta(value, itemDescriptor as? NodeDescriptor)) + this[key] = MetaItem.NodeItem( + JsonMeta( + value, + itemDescriptor as? NodeDescriptor + ) + ) } is JsonArray -> { when { diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt index b37188b4..e5cda8f6 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt @@ -3,13 +3,9 @@ package hep.dataforge.meta import hep.dataforge.meta.Meta.Companion.VALUE_KEY import hep.dataforge.meta.MetaItem.NodeItem import hep.dataforge.meta.MetaItem.ValueItem -import hep.dataforge.meta.serialization.toJson import hep.dataforge.names.* -import hep.dataforge.values.EnumValue -import hep.dataforge.values.Null -import hep.dataforge.values.Value -import hep.dataforge.values.boolean -import kotlinx.serialization.Serializable +import hep.dataforge.values.* +import kotlinx.serialization.* /** @@ -22,11 +18,33 @@ sealed class MetaItem { @Serializable data class ValueItem(val value: Value) : MetaItem() { override fun toString(): String = value.toString() + + @Serializer(ValueItem::class) + companion object : KSerializer { + 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) + } + } } @Serializable data class NodeItem(val node: M) : MetaItem() { override fun toString(): String = node.toString() + + @Serializer(NodeItem::class) + companion object : KSerializer> { + override val descriptor: SerialDescriptor get() = ValueSerializer.descriptor + + override fun deserialize(decoder: Decoder): NodeItem<*> = NodeItem(MetaSerializer.deserialize(decoder)) + + override fun serialize(encoder: Encoder, value: NodeItem<*>) { + MetaSerializer.serialize(encoder, value.node) + } + } } companion object { @@ -72,6 +90,7 @@ interface Meta : MetaRepr { companion object { const val TYPE = "meta" + /** * A key for single value node */ @@ -101,6 +120,7 @@ operator fun Meta?.get(name: Name): MetaItem<*>? { } operator fun Meta?.get(token: NameToken): MetaItem<*>? = this?.items?.get(token) + /** * Parse [Name] from [key] using full name notation and pass it to [Meta.get] */ diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt new file mode 100644 index 00000000..63a45664 --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/MetaSerializer.kt @@ -0,0 +1,53 @@ +package hep.dataforge.meta + +import hep.dataforge.names.NameToken +import kotlinx.serialization.* +import kotlinx.serialization.builtins.MapSerializer +import kotlinx.serialization.json.JsonInput +import kotlinx.serialization.json.JsonObjectSerializer +import kotlinx.serialization.json.JsonOutput + + +private class DeserializedMeta(override val items: Map>) : MetaBase() + +/** + * Serialized for meta + */ +@Serializer(Meta::class) +object MetaSerializer : KSerializer { + private val mapSerializer = MapSerializer( + NameToken.serializer(), + MetaItem.serializer(MetaSerializer) + ) + + override val descriptor: SerialDescriptor get() = mapSerializer.descriptor + + override fun deserialize(decoder: Decoder): Meta { + return if (decoder is JsonInput) { + JsonObjectSerializer.deserialize(decoder).toMeta() + } else { + DeserializedMeta(mapSerializer.deserialize(decoder)) + } + } + + override fun serialize(encoder: Encoder, value: Meta) { + if (encoder is JsonOutput) { + JsonObjectSerializer.serialize(encoder, value.toJson()) + } else { + mapSerializer.serialize(encoder, value.items) + } + } +} + +@Serializer(Config::class) +object ConfigSerializer : KSerializer { + 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) + } +} \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt index ddf049e3..df3e97a5 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt @@ -20,7 +20,7 @@ fun Meta.toMap(descriptor: NodeDescriptor? = null): Map { * Convert map of maps to meta */ @DFExperimental -fun Map.toMeta(descriptor: NodeDescriptor? = null): Meta = buildMeta { +fun Map.toMeta(descriptor: NodeDescriptor? = null): Meta = Meta { entries.forEach { (key, value) -> @Suppress("UNCHECKED_CAST") when (value) { diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/scheme/ConfigurableDelegate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/scheme/ConfigurableDelegate.kt index c6e9a44a..da02c30e 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/scheme/ConfigurableDelegate.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/scheme/ConfigurableDelegate.kt @@ -201,7 +201,7 @@ fun Configurable.doubleArray(vararg doubles: Double, key: Name? = null): ReadWri fun Configurable.config(key: Name? = null): ReadWriteProperty = config.node(key) -fun Configurable.node(key: Name? = null): ReadWriteProperty = item().map( +fun Configurable.node(key: Name? = null): ReadWriteProperty = item(key).map( reader = { it.node }, writer = { it?.let { MetaItem.NodeItem(it) } } ) diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/scheme/Scheme.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/scheme/Scheme.kt index 78d0a511..8e74ba7b 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/scheme/Scheme.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/scheme/Scheme.kt @@ -39,7 +39,7 @@ open class Scheme() : Configurable, Described, MetaRepr { */ open val defaultLayer: Meta get() = DefaultLayer(Name.EMPTY) - override fun toMeta(): Meta = Laminate(config, defaultLayer) + override fun toMeta(): Laminate = Laminate(config, defaultLayer) private inner class DefaultLayer(val path: Name) : MetaBase() { override val items: Map> = @@ -87,10 +87,4 @@ open class MetaScheme( fun Meta.asScheme() = MetaScheme(this) -fun Meta.toScheme(spec: Specification, block: T.() -> Unit) = spec.wrap(this).apply(block) - -/** - * Create a snapshot laminate - */ -fun Scheme.toMeta(): Laminate = - Laminate(config, defaultLayer) \ No newline at end of file +fun Meta.toScheme(spec: Specification, block: T.() -> Unit) = spec.wrap(this).apply(block) \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serialization/MetaSerializer.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serialization/MetaSerializer.kt deleted file mode 100644 index a98aa4c0..00000000 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serialization/MetaSerializer.kt +++ /dev/null @@ -1,110 +0,0 @@ -package hep.dataforge.meta.serialization - -import hep.dataforge.meta.* -import hep.dataforge.names.NameToken -import hep.dataforge.values.* -import kotlinx.serialization.* -import kotlinx.serialization.builtins.MapSerializer -import kotlinx.serialization.builtins.list -import kotlinx.serialization.builtins.serializer -import kotlinx.serialization.json.JsonInput -import kotlinx.serialization.json.JsonObjectSerializer -import kotlinx.serialization.json.JsonOutput - - -@Serializer(Value::class) -@OptIn(InternalSerializationApi::class) -object ValueSerializer : KSerializer { - // private val valueTypeSerializer = EnumSerializer(ValueType::class) - private val listSerializer by lazy { ValueSerializer.list } - - override val descriptor: SerialDescriptor = SerialDescriptor("Value") { - boolean("isList") - enum("valueType") - string("value") - } - - private fun Decoder.decodeValue(): Value { - return when (decode(ValueType.serializer())) { - ValueType.NULL -> Null - ValueType.NUMBER -> decodeDouble().asValue() //TODO differentiate? - ValueType.BOOLEAN -> decodeBoolean().asValue() - ValueType.STRING -> decodeString().asValue() - } - } - - - override fun deserialize(decoder: Decoder): Value { - val isList = decoder.decodeBoolean() - return if (isList) { - listSerializer.deserialize(decoder).asValue() - } else { - decoder.decodeValue() - } - } - - private fun Encoder.encodeValue(value: Value) { - encode(ValueType.serializer(), value.type) - when (value.type) { - ValueType.NULL -> { - // do nothing - } - ValueType.NUMBER -> encodeDouble(value.double) - ValueType.BOOLEAN -> encodeBoolean(value.boolean) - ValueType.STRING -> encodeString(value.string) - } - } - - override fun serialize(encoder: Encoder, value: Value) { - encoder.encodeBoolean(value.isList()) - if (value.isList()) { - listSerializer.serialize(encoder, value.list) - } else { - encoder.encodeValue(value) - } - } -} - -private class DeserializedMeta(override val items: Map>) : MetaBase() - -/** - * Serialized for meta - */ -@Serializer(Meta::class) -object MetaSerializer : KSerializer { - private val mapSerializer = MapSerializer( - String.serializer(), - MetaItem.serializer(MetaSerializer) - ) - - override val descriptor: SerialDescriptor get() = mapSerializer.descriptor - - override fun deserialize(decoder: Decoder): Meta { - return if (decoder is JsonInput) { - JsonObjectSerializer.deserialize(decoder).toMeta() - } else { - DeserializedMeta(mapSerializer.deserialize(decoder).mapKeys { NameToken(it.key) }) - } - } - - override fun serialize(encoder: Encoder, value: Meta) { - if (encoder is JsonOutput) { - JsonObjectSerializer.serialize(encoder, value.toJson()) - } else { - mapSerializer.serialize(encoder, value.items.mapKeys { it.key.toString() }) - } - } -} - -@Serializer(Config::class) -object ConfigSerializer : KSerializer { - override val descriptor: SerialDescriptor = MetaSerializer.descriptor - - override fun deserialize(decoder: Decoder): Config { - return MetaSerializer.deserialize(decoder).asConfig() - } - - override fun serialize(encoder: Encoder, value: Config) { - MetaSerializer.serialize(encoder, value) - } -} \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serialization/serializationUtils.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serializationUtils.kt similarity index 60% rename from dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serialization/serializationUtils.kt rename to dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serializationUtils.kt index a92609e9..16c58bdc 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serialization/serializationUtils.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/serializationUtils.kt @@ -1,33 +1,36 @@ -package hep.dataforge.meta.serialization +package hep.dataforge.meta -import hep.dataforge.meta.DFExperimental import kotlinx.serialization.* import kotlinx.serialization.builtins.DoubleArraySerializer -import kotlinx.serialization.internal.* +import kotlinx.serialization.builtins.serializer fun SerialDescriptorBuilder.boolean(name: String, isOptional: Boolean = false, vararg annotations: Annotation) = - element(name, PrimitiveDescriptor(name, PrimitiveKind.BOOLEAN), isOptional = isOptional, annotations = annotations.toList()) + element(name, Boolean.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList()) fun SerialDescriptorBuilder.string(name: String, isOptional: Boolean = false, vararg annotations: Annotation) = - element(name, PrimitiveDescriptor(name, PrimitiveKind.STRING), isOptional = isOptional, annotations = annotations.toList()) + element(name, String.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList()) fun SerialDescriptorBuilder.int(name: String, isOptional: Boolean = false, vararg annotations: Annotation) = - element(name, PrimitiveDescriptor(name, PrimitiveKind.INT), isOptional = isOptional, annotations = annotations.toList()) + element(name, Int.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList()) fun SerialDescriptorBuilder.double(name: String, isOptional: Boolean = false, vararg annotations: Annotation) = - element(name,PrimitiveDescriptor(name, PrimitiveKind.DOUBLE), isOptional = isOptional, annotations = annotations.toList()) + element(name, Double.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList()) fun SerialDescriptorBuilder.float(name: String, isOptional: Boolean = false, vararg annotations: Annotation) = - element(name, PrimitiveDescriptor(name, PrimitiveKind.FLOAT), isOptional = isOptional, annotations = annotations.toList()) + element(name, Float.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList()) fun SerialDescriptorBuilder.long(name: String, isOptional: Boolean = false, vararg annotations: Annotation) = - element(name, PrimitiveDescriptor(name, PrimitiveKind.LONG), isOptional = isOptional, annotations = annotations.toList()) + element(name, Long.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList()) fun SerialDescriptorBuilder.doubleArray(name: String, isOptional: Boolean = false, vararg annotations: Annotation) = element(name, DoubleArraySerializer().descriptor, isOptional = isOptional, annotations = annotations.toList()) @OptIn(InternalSerializationApi::class) -inline fun > SerialDescriptorBuilder.enum(name: String, isOptional: Boolean = false, vararg annotations: Annotation) { +inline fun > SerialDescriptorBuilder.enum( + name: String, + isOptional: Boolean = false, + vararg annotations: Annotation +) { val enumDescriptor = SerialDescriptor(serialName, UnionKind.ENUM_KIND) { enumValues().forEach { val fqn = "$serialName.${it.name}" @@ -38,17 +41,11 @@ inline fun > SerialDescriptorBuilder.enum(name: String, isOp element(name, enumDescriptor, isOptional = isOptional, annotations = annotations.toList()) } -//inline fun KSerializer.descriptor( -// name: String, -// block: SerialDescriptorBuilder.() -> Unit -//): SerialDescriptor = -// SerialDescriptorBuilder(SerialClassDescImpl(name)).apply(block).build() - @DFExperimental inline fun Decoder.decodeStructure( desc: SerialDescriptor, vararg typeParams: KSerializer<*> = emptyArray(), - crossinline block: CompositeDecoder.() -> R + crossinline block: CompositeDecoder.() -> R ): R { val decoder = beginStructure(desc, *typeParams) val res = decoder.block() @@ -56,6 +53,7 @@ inline fun Decoder.decodeStructure( return res } +@DFExperimental inline fun Encoder.encodeStructure( desc: SerialDescriptor, vararg typeParams: KSerializer<*> = emptyArray(), diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt index 255a2ffd..2b8908ed 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/names/Name.kt @@ -53,14 +53,13 @@ class Name(val tokens: List) { } } - @Serializer(Name::class) - companion object: KSerializer { + companion object : KSerializer { const val NAME_SEPARATOR = "." val EMPTY = Name(emptyList()) - override val descriptor: SerialDescriptor = PrimitiveDescriptor("Name", PrimitiveKind.STRING) + override val descriptor: SerialDescriptor = PrimitiveDescriptor("hep.dataforge.names.Name", PrimitiveKind.STRING) override fun deserialize(decoder: Decoder): Name { return decoder.decodeString().toName() @@ -99,8 +98,8 @@ data class NameToken(val body: String, val index: String = "") { fun hasIndex() = index.isNotEmpty() @Serializer(NameToken::class) - companion object :KSerializer{ - override val descriptor: SerialDescriptor = PrimitiveDescriptor("NameToken", PrimitiveKind.STRING) + companion object : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveDescriptor("hep.dataforge.names.NameToken", PrimitiveKind.STRING) override fun deserialize(decoder: Decoder): NameToken { return decoder.decodeString().toName().first()!! diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt new file mode 100644 index 00000000..8055b554 --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/values/ValueSerializer.kt @@ -0,0 +1,59 @@ +package hep.dataforge.values + +import hep.dataforge.meta.boolean +import hep.dataforge.meta.enum +import hep.dataforge.meta.string +import kotlinx.serialization.* +import kotlinx.serialization.builtins.list + +@Serializer(Value::class) +object ValueSerializer : KSerializer { + private val listSerializer by lazy { ValueSerializer.list } + + override val descriptor: SerialDescriptor = + SerialDescriptor("hep.dataforge.values.Value") { + boolean("isList") + enum("valueType") + string("value") + } + + private fun Decoder.decodeValue(): Value { + return when (decode(ValueType.serializer())) { + ValueType.NULL -> Null + ValueType.NUMBER -> decodeDouble().asValue() //TODO differentiate? + ValueType.BOOLEAN -> decodeBoolean().asValue() + ValueType.STRING -> decodeString().asValue() + } + } + + + override fun deserialize(decoder: Decoder): Value { + val isList = decoder.decodeBoolean() + return if (isList) { + listSerializer.deserialize(decoder).asValue() + } else { + decoder.decodeValue() + } + } + + private fun Encoder.encodeValue(value: Value) { + encode(ValueType.serializer(), value.type) + when (value.type) { + ValueType.NULL -> { + // do nothing + } + ValueType.NUMBER -> encodeDouble(value.double) + ValueType.BOOLEAN -> encodeBoolean(value.boolean) + ValueType.STRING -> encodeString(value.string) + } + } + + override fun serialize(encoder: Encoder, value: Value) { + encoder.encodeBoolean(value.isList()) + if (value.isList()) { + listSerializer.serialize(encoder, value.list) + } else { + encoder.encodeValue(value) + } + } +} \ No newline at end of file diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaExtensionTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaExtensionTest.kt index f2fffd19..0f4c19be 100644 --- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaExtensionTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaExtensionTest.kt @@ -11,12 +11,12 @@ class MetaExtensionTest { @Test fun testEnum(){ - val meta = buildMeta{"enum" put TestEnum.test} + val meta = Meta{"enum" put TestEnum.test} meta["enum"].enum() } @Test fun testEnumByString(){ - val meta = buildMeta{"enum" put TestEnum.test.name} + val meta = Meta{"enum" put TestEnum.test.name} println(meta["enum"].enum()) } diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaTest.kt index fb424116..c55cd4ad 100644 --- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaTest.kt @@ -16,13 +16,13 @@ class MetaTest { @Test fun metaEqualityTest() { - val meta1 = buildMeta { + val meta1 = Meta { "a" put 22 "b" put { "c" put "ddd" } } - val meta2 = buildMeta { + val meta2 = Meta { "b" put { "c" put "ddd" } @@ -33,13 +33,13 @@ class MetaTest { @Test fun metaToMap(){ - val meta = buildMeta { + val meta = Meta { "a" put 22 "b" put { "c" put "ddd" } "list" put (0..4).map { - buildMeta { + Meta { "value" put it } } diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MutableMetaTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MutableMetaTest.kt index 194c77e3..ba44edec 100644 --- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MutableMetaTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MutableMetaTest.kt @@ -6,7 +6,7 @@ import kotlin.test.assertEquals class MutableMetaTest{ @Test fun testRemove(){ - val meta = buildMeta { + val meta = Meta { "aNode" put { "innerNode" put { "innerValue" put true diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SchemeTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SchemeTest.kt index 09a3e03c..bcebedc6 100644 --- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SchemeTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/SchemeTest.kt @@ -2,7 +2,6 @@ package hep.dataforge.meta import hep.dataforge.meta.scheme.asScheme import hep.dataforge.meta.scheme.getProperty -import hep.dataforge.meta.scheme.toMeta import kotlin.test.Test import kotlin.test.assertEquals @@ -10,7 +9,7 @@ import kotlin.test.assertEquals class SchemeTest{ @Test fun testMetaScheme(){ - val styled = buildMeta { + val styled = Meta { repeat(10){ "b.a[$it]" put { "d" put it diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt index 29ce27b2..1180ca23 100644 --- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt +++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt @@ -15,7 +15,7 @@ import kotlinx.io.asBinary suspend fun Table.wrap(): Envelope = Envelope { meta { header.forEachIndexed { index, columnHeader -> - set("column", index.toString(), buildMeta { + set("column", index.toString(), Meta { "name" put columnHeader.name if (!columnHeader.meta.isEmpty()) { "meta" put columnHeader.meta diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt index 72402a17..ed5ab7f0 100644 --- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt +++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Dependency.kt @@ -5,7 +5,6 @@ import hep.dataforge.data.DataNode import hep.dataforge.data.filter import hep.dataforge.meta.Meta import hep.dataforge.meta.MetaRepr -import hep.dataforge.meta.buildMeta import hep.dataforge.names.Name import hep.dataforge.names.asName import hep.dataforge.names.isEmpty @@ -28,7 +27,7 @@ class DataDependency(val filter: DataFilter, val placement: Name = Name.EMPTY) : } } - override fun toMeta(): Meta = buildMeta { + override fun toMeta(): Meta = Meta { "data" put filter.config "to" put placement.toString() } @@ -41,7 +40,7 @@ class AllDataDependency(val placement: Name = Name.EMPTY) : Dependency() { DataNode.invoke(Any::class) { this[placement] = workspace.data } } - override fun toMeta() = buildMeta { + override fun toMeta() = Meta { "data" put "@all" "to" put placement.toString() } @@ -69,7 +68,7 @@ abstract class TaskDependency( } } - override fun toMeta(): Meta = buildMeta { + override fun toMeta(): Meta = Meta { "task" put name.toString() "meta" put meta "to" put placement.toString() diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt index ede9efaa..a811f428 100644 --- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt +++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskModel.kt @@ -29,7 +29,7 @@ data class TaskModel( //TODO provide a way to get task descriptor //TODO add pre-run check of task result type? - override fun toMeta(): Meta = buildMeta { + override fun toMeta(): Meta = Meta { "name" put name.toString() "meta" put meta "dependsOn" put { @@ -98,7 +98,7 @@ fun TaskDependencyContainer.dependsOn( placement: Name = Name.EMPTY, metaBuilder: MetaBuilder.() -> Unit ): DirectTaskDependency = - dependsOn(task, placement, buildMeta(metaBuilder)) + dependsOn(task, placement, Meta(metaBuilder)) /** * Add custom data dependency diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt index 31da6c56..ac2b1131 100644 --- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt +++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/Workspace.kt @@ -8,7 +8,6 @@ import hep.dataforge.data.DataNode import hep.dataforge.data.dataSequence import hep.dataforge.meta.Meta import hep.dataforge.meta.MetaBuilder -import hep.dataforge.meta.buildMeta import hep.dataforge.names.Name import hep.dataforge.names.toName import hep.dataforge.provider.Provider @@ -76,7 +75,7 @@ fun Workspace.run(task: String, meta: Meta) = tasks[task.toName()]?.let { run(it, meta) } ?: error("Task with name $task not found") fun Workspace.run(task: String, block: MetaBuilder.() -> Unit = {}) = - run(task, buildMeta(block)) + run(task, Meta(block)) fun Workspace.run(task: Task, metaBuilder: MetaBuilder.() -> Unit = {}): DataNode = - run(task, buildMeta(metaBuilder)) \ No newline at end of file + run(task, Meta(metaBuilder)) \ No newline at end of file diff --git a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt index 7b831a50..3bc1ffcf 100644 --- a/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt +++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/WorkspaceBuilder.kt @@ -52,7 +52,7 @@ fun WorkspaceBuilder.data( fun WorkspaceBuilder.target(name: String, block: MetaBuilder.() -> Unit) { - targets[name] = buildMeta(block).seal() + targets[name] = Meta(block).seal() } /**