diff --git a/.space.kts b/.space.kts deleted file mode 100644 index 45b2ed53..00000000 --- a/.space.kts +++ /dev/null @@ -1,4 +0,0 @@ -job("Build") { - gradlew("openjdk:11", "build") -} - diff --git a/CHANGELOG.md b/CHANGELOG.md index ee7190af..e32cc6bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,15 +14,41 @@ ### Security +## 0.7.0 - 2023-11-26 + +### Added + +- Obligatory `type: KType` and `descriptor` property for `MetaConverters` +- Added separate `Meta`, `SealedMeta` and `ObservableMutableMeta` builders. + +### Changed + +- Meta converter `metaToObject` returns a non-nullable type. Additional method `metaToObjectOrNull` for nullable return. +- Kotlin 1.9.20. +- Migrated from ktor-io to kotlinx-io. +- `MutableMeta` builder now returns a simplified version of meta that does not hold listeners. +- More concise names for read/write methods in IO. +- Remove unnecessary confusion with `get`/`getMeta` by removing `getMeta` from the interface. + +### Deprecated + +- `String.parseValue` is replaced with `Value.parse` + +### Fixed + +- Memory leak in SealedMeta builder + ## 0.6.2 - 2023-07-29 ### Changed + - Meta to Json serializer now serializes a single item with index as an array. It is important for plotly integration. - Meta to Json serializes Meta without children a value as literal or array instead of an object with `@value` field. ## 0.6.1 - 2023-03-31 ### Added + - File cache for workspace - Smart task metadata transformation for workspace - Add `readOnly` property to descriptors @@ -32,6 +58,7 @@ - More fine-grained types in Action builders. ### Changed + - `Name::replaceLast` API - `PluginFactory` no longer requires plugin class - Collection toMap -> associateByName @@ -53,9 +80,11 @@ - Separate interfaces for `IOReader` and `IOWriter` ### Deprecated + - Context.fetch -> Context.request ### Fixed + - `readDataDirectory` does not split names with dots - Front matter reader does not crash on non-UTF files - Meta file name in readMeta from directory @@ -64,10 +93,12 @@ ## 0.5.2 ### Added + - Yaml plugin - Partial fix to #53 ### Fixed + - MutableMetaImpl attachment and checks - Listeners in observable meta are replaced by lists - JS number comparison bug. @@ -75,9 +106,11 @@ ## 0.5.0 ### Added + - Experimental `listOfSpec` delegate. ### Changed + - **API breaking** Config is deprecated, use `ObservableMeta` instead. - **API breaking** Descriptor no has a member property `defaultValue` instead of `defaultItem()` extension. It caches default value state on the first call. It is done because computing default on each call is too expensive. - Kotlin 1.5.10 @@ -88,24 +121,28 @@ - **API breaking** Configurable`config` changed to `meta` ### Removed + - `Config` - Public PluginManager mutability - Tables and tables-exposed moved to the separate project `tables.kt` - BinaryMetaFormat. Use CBOR encoding instead ### Fixed + - Proper json array index treatment. - Proper json index for single-value array. ## 0.4.0 ### Added + - LogManager plugin - dataforge-context API dependency on SLF4j - Context `withEnv` and `fetch` methods to manipulate plugins without changing plugins after creation. - Split `ItemDescriptor` into builder and read-only part ### Changed + - Kotlin-logging moved from common to JVM and JS. Replaced by console for native. - Package changed to `space.kscience` - Scheme made observable @@ -115,18 +152,22 @@ - Refactor loggers ### Deprecated + - Direct use of PluginManager ### Removed + - Common dependency on Kotlin-logging - Kotlinx-io fork dependency. Replaced by Ktor-io. ### Fixed + - Scheme properties properly handle children property change. ## 0.3.0 ### Added + - Yaml meta format based on yaml.kt - `Path` builders - Special ValueType for lists @@ -134,6 +175,7 @@ - Multiplatform yaml meta ### Changed + - `ListValue` and `DoubleArrayValue` implement `Iterable`. - Changed the logic of `Value::isList` to check for type instead of size - `Meta{}` builder made inline @@ -150,6 +192,7 @@ ## 0.2.0 ### Changed + - Context content resolution refactor - Kotlin 1.4.10 (build tools 0.6.0) - Empty query in Name is null instead of "" @@ -159,13 +202,16 @@ - Configurable is no longer MutableItemProvider. All functionality moved to Scheme. ### Deprecated + - Context activation API - TextRenderer ### Removed + - Functional server prototype - `dataforge-output` module ### Fixed + - Global context CoroutineScope resolution - Library mode compliance diff --git a/README.md b/README.md index a973a25f..da910804 100644 --- a/README.md +++ b/README.md @@ -5,32 +5,29 @@ ### [dataforge-context](dataforge-context) -> +> Context and provider definitions > > **Maturity**: DEVELOPMENT ### [dataforge-data](dataforge-data) -> > > **Maturity**: EXPERIMENTAL ### [dataforge-io](dataforge-io) -> +> IO module > -> **Maturity**: PROTOTYPE +> **Maturity**: EXPERIMENTAL ### [dataforge-meta](dataforge-meta) -> +> Meta definition and basic operations on meta > > **Maturity**: DEVELOPMENT ### [dataforge-scripting](dataforge-scripting) -> > > **Maturity**: PROTOTYPE ### [dataforge-workspace](dataforge-workspace) -> > > **Maturity**: EXPERIMENTAL diff --git a/build.gradle.kts b/build.gradle.kts index bbab94eb..4b5fe48c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import space.kscience.gradle.isInDevelopment import space.kscience.gradle.useApache2Licence import space.kscience.gradle.useSPCTeam @@ -9,7 +8,7 @@ plugins { allprojects { group = "space.kscience" - version = "0.6.2" + version = "0.7.0" } subprojects { @@ -31,14 +30,7 @@ ksciencePublish { useApache2Licence() useSPCTeam() } - github("dataforge-core", "SciProgCentre") - space( - if (isInDevelopment) { - "https://maven.pkg.jetbrains.space/spc/p/sci/dev" - } else { - "https://maven.pkg.jetbrains.space/spc/p/sci/maven" - } - ) + repository("spc","https://maven.sciprog.center/kscience") sonatype() } diff --git a/dataforge-context/README.md b/dataforge-context/README.md index 06e06f3a..905171b1 100644 --- a/dataforge-context/README.md +++ b/dataforge-context/README.md @@ -6,27 +6,18 @@ Context and provider definitions ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-context:0.6.2-dev-2`. +The Maven coordinates of this project are `space.kscience:dataforge-context:0.7.0`. -**Gradle Groovy:** -```groovy -repositories { - maven { url 'https://repo.kotlin.link' } - mavenCentral() -} - -dependencies { - implementation 'space.kscience:dataforge-context:0.6.2-dev-2' -} -``` **Gradle Kotlin DSL:** ```kotlin repositories { maven("https://repo.kotlin.link") + //uncomment to access development builds + //maven("https://maven.pkg.jetbrains.space/spc/p/sci/dev") mavenCentral() } dependencies { - implementation("space.kscience:dataforge-context:0.6.2-dev-2") + implementation("space.kscience:dataforge-context:0.7.0") } ``` diff --git a/dataforge-context/api/dataforge-context.api b/dataforge-context/api/dataforge-context.api index a3193093..eac8e52c 100644 --- a/dataforge-context/api/dataforge-context.api +++ b/dataforge-context/api/dataforge-context.api @@ -195,7 +195,6 @@ public final class space/kscience/dataforge/context/PluginManager : java/lang/It public final class space/kscience/dataforge/context/PluginTag : space/kscience/dataforge/meta/MetaRepr { public static final field Companion Lspace/kscience/dataforge/context/PluginTag$Companion; public static final field DATAFORGE_GROUP Ljava/lang/String; - public synthetic fun (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ljava/lang/String; @@ -211,7 +210,6 @@ public final class space/kscience/dataforge/context/PluginTag : space/kscience/d public final fun matches (Lspace/kscience/dataforge/context/PluginTag;)Z public fun toMeta ()Lspace/kscience/dataforge/meta/Meta; public fun toString ()Ljava/lang/String; - public static final synthetic fun write$Self (Lspace/kscience/dataforge/context/PluginTag;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V } public final class space/kscience/dataforge/context/PluginTag$$serializer : kotlinx/serialization/internal/GeneratedSerializer { diff --git a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Plugin.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Plugin.kt index 0621604e..152f5a76 100644 --- a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Plugin.kt +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Plugin.kt @@ -3,8 +3,8 @@ package space.kscience.dataforge.context import space.kscience.dataforge.context.Plugin.Companion.TARGET import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MetaRepr +import space.kscience.dataforge.misc.DfId import space.kscience.dataforge.misc.Named -import space.kscience.dataforge.misc.Type import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.parseAsName import space.kscience.dataforge.provider.Provider @@ -18,7 +18,7 @@ import space.kscience.dataforge.provider.Provider * * create - configure - attach - detach - destroy */ -@Type(TARGET) +@DfId(TARGET) public interface Plugin : Named, ContextAware, Provider, MetaRepr { /** diff --git a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/PluginFactory.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/PluginFactory.kt index 308e3bbb..0273d327 100644 --- a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/PluginFactory.kt +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/PluginFactory.kt @@ -1,9 +1,9 @@ package space.kscience.dataforge.context import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.misc.Type +import space.kscience.dataforge.misc.DfId -@Type(PluginFactory.TYPE) +@DfId(PluginFactory.TYPE) public interface PluginFactory : Factory { public val tag: PluginTag diff --git a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/MetaProperty.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/MetaProperty.kt index 23601141..e79ce931 100644 --- a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/MetaProperty.kt +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/MetaProperty.kt @@ -1,7 +1,8 @@ package space.kscience.dataforge.properties -import space.kscience.dataforge.meta.* +import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.meta.ObservableMutableMeta import space.kscience.dataforge.meta.transformations.MetaConverter import space.kscience.dataforge.meta.transformations.nullableMetaToObject import space.kscience.dataforge.meta.transformations.nullableObjectToMeta @@ -24,7 +25,7 @@ public class MetaProperty( override fun onChange(owner: Any?, callback: (T?) -> Unit) { meta.onChange(owner) { name -> - if (name.startsWith(this@MetaProperty.name)) callback(converter.nullableMetaToObject(get(name))) + if (name.startsWith(this@MetaProperty.name)) callback(converter.nullableMetaToObject(this[name])) } } diff --git a/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/provider/dfType.kt b/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/provider/dfType.kt index b44e509b..ab34ea50 100644 --- a/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/provider/dfType.kt +++ b/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/provider/dfType.kt @@ -4,29 +4,29 @@ import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.PluginBuilder import space.kscience.dataforge.context.gather import space.kscience.dataforge.misc.DFExperimental +import space.kscience.dataforge.misc.DfId import space.kscience.dataforge.misc.Named -import space.kscience.dataforge.misc.Type import space.kscience.dataforge.names.Name import kotlin.reflect.KClass import kotlin.reflect.full.findAnnotation @DFExperimental -public val KClass<*>.dfType: String - get() = findAnnotation()?.id ?: simpleName ?: "" +public val KClass<*>.dfId: String + get() = findAnnotation()?.id ?: simpleName ?: "" /** - * Provide an object with given name inferring target from its type using [Type] annotation + * Provide an object with given name inferring target from its type using [DfId] annotation */ @DFExperimental public inline fun Provider.provideByType(name: String): T? { - val target = T::class.dfType + val target = T::class.dfId return provide(target, name) } @DFExperimental public inline fun Provider.top(): Map { - val target = T::class.dfType + val target = T::class.dfId return top(target) } @@ -35,15 +35,15 @@ public inline fun Provider.top(): Map { */ @DFExperimental public inline fun Context.gather(inherit: Boolean = true): Map = - gather(T::class.dfType, inherit) + gather(T::class.dfId, inherit) @DFExperimental public inline fun PluginBuilder.provides(items: Map) { - provides(T::class.dfType, items) + provides(T::class.dfId, items) } @DFExperimental public inline fun PluginBuilder.provides(vararg items: Named) { - provides(T::class.dfType, *items) + provides(T::class.dfId, *items) } diff --git a/dataforge-data/README.md b/dataforge-data/README.md index 3b74b2de..5935af6e 100644 --- a/dataforge-data/README.md +++ b/dataforge-data/README.md @@ -6,27 +6,18 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-data:0.6.2-dev-2`. +The Maven coordinates of this project are `space.kscience:dataforge-data:0.7.0`. -**Gradle Groovy:** -```groovy -repositories { - maven { url 'https://repo.kotlin.link' } - mavenCentral() -} - -dependencies { - implementation 'space.kscience:dataforge-data:0.6.2-dev-2' -} -``` **Gradle Kotlin DSL:** ```kotlin repositories { maven("https://repo.kotlin.link") + //uncomment to access development builds + //maven("https://maven.pkg.jetbrains.space/spc/p/sci/dev") mavenCentral() } dependencies { - implementation("space.kscience:dataforge-data:0.6.2-dev-2") + implementation("space.kscience:dataforge-data:0.7.0") } ``` diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/Data.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/Data.kt index e169b4a5..984582e5 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/Data.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/Data.kt @@ -5,7 +5,7 @@ import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MetaRepr import space.kscience.dataforge.meta.isEmpty import space.kscience.dataforge.misc.DFInternal -import space.kscience.dataforge.misc.Type +import space.kscience.dataforge.misc.DfId import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext import kotlin.reflect.KType @@ -14,7 +14,7 @@ import kotlin.reflect.typeOf /** * A data element characterized by its meta */ -@Type(Data.TYPE) +@DfId(Data.TYPE) public interface Data : Goal, MetaRepr { /** * Type marker for the data. The type is known before the calculation takes place so it could be checked. diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSet.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSet.kt index 36428cd4..44639653 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSet.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSet.kt @@ -6,7 +6,6 @@ import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.mapNotNull import space.kscience.dataforge.data.Data.Companion.TYPE_OF_NOTHING import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.set import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.endsWith diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataTree.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataTree.kt index b70744ce..bafcbea2 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataTree.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataTree.kt @@ -2,7 +2,7 @@ package space.kscience.dataforge.data import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.misc.DFInternal -import space.kscience.dataforge.misc.Type +import space.kscience.dataforge.misc.DfId import space.kscience.dataforge.names.* import kotlin.collections.component1 import kotlin.collections.component2 @@ -31,7 +31,7 @@ public val DataTreeItem.type: KType /** * A tree-like [DataSet] grouped into the node. All data inside the node must inherit its type */ -@Type(DataTree.TYPE) +@DfId(DataTree.TYPE) public interface DataTree : DataSet { /** diff --git a/dataforge-io/README.md b/dataforge-io/README.md index 6ce35db3..ec431a04 100644 --- a/dataforge-io/README.md +++ b/dataforge-io/README.md @@ -6,27 +6,18 @@ IO module ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-io:0.6.2-dev-2`. +The Maven coordinates of this project are `space.kscience:dataforge-io:0.7.0`. -**Gradle Groovy:** -```groovy -repositories { - maven { url 'https://repo.kotlin.link' } - mavenCentral() -} - -dependencies { - implementation 'space.kscience:dataforge-io:0.6.2-dev-2' -} -``` **Gradle Kotlin DSL:** ```kotlin repositories { maven("https://repo.kotlin.link") + //uncomment to access development builds + //maven("https://maven.pkg.jetbrains.space/spc/p/sci/dev") mavenCentral() } dependencies { - implementation("space.kscience:dataforge-io:0.6.2-dev-2") + implementation("space.kscience:dataforge-io:0.7.0") } ``` diff --git a/dataforge-io/build.gradle.kts b/dataforge-io/build.gradle.kts index 9f2030c7..6d3c888c 100644 --- a/dataforge-io/build.gradle.kts +++ b/dataforge-io/build.gradle.kts @@ -1,11 +1,11 @@ -import space.kscience.gradle.KScienceVersions - plugins { id("space.kscience.gradle.mpp") } description = "IO module" +val ioVersion = "0.2.1" + kscience { jvm() js() @@ -15,11 +15,12 @@ kscience { cbor() } dependencies { - api(project(":dataforge-context")) - api("io.ktor:ktor-io:${KScienceVersions.ktorVersion}") + api(projects.dataforgeContext) + api("org.jetbrains.kotlinx:kotlinx-io-core:$ioVersion") + api("org.jetbrains.kotlinx:kotlinx-io-bytestring:$ioVersion") } } -readme { - maturity = space.kscience.gradle.Maturity.PROTOTYPE +readme{ + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL } \ No newline at end of file diff --git a/dataforge-io/dataforge-io-yaml/README.md b/dataforge-io/dataforge-io-yaml/README.md index 452ba504..06a0efb4 100644 --- a/dataforge-io/dataforge-io-yaml/README.md +++ b/dataforge-io/dataforge-io-yaml/README.md @@ -6,27 +6,18 @@ YAML meta IO ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-io-yaml:0.6.2-dev-2`. +The Maven coordinates of this project are `space.kscience:dataforge-io-yaml:0.7.0`. -**Gradle Groovy:** -```groovy -repositories { - maven { url 'https://repo.kotlin.link' } - mavenCentral() -} - -dependencies { - implementation 'space.kscience:dataforge-io-yaml:0.6.2-dev-2' -} -``` **Gradle Kotlin DSL:** ```kotlin repositories { maven("https://repo.kotlin.link") + //uncomment to access development builds + //maven("https://maven.pkg.jetbrains.space/spc/p/sci/dev") mavenCentral() } dependencies { - implementation("space.kscience:dataforge-io-yaml:0.6.2-dev-2") + implementation("space.kscience:dataforge-io-yaml:0.7.0") } ``` diff --git a/dataforge-io/dataforge-io-yaml/src/commonMain/kotlin/space/kscience/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt b/dataforge-io/dataforge-io-yaml/src/commonMain/kotlin/space/kscience/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt index 046f08fa..f999ad5b 100644 --- a/dataforge-io/dataforge-io-yaml/src/commonMain/kotlin/space/kscience/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt +++ b/dataforge-io/dataforge-io-yaml/src/commonMain/kotlin/space/kscience/dataforge/io/yaml/FrontMatterEnvelopeFormat.kt @@ -1,7 +1,11 @@ package space.kscience.dataforge.io.yaml -import io.ktor.utils.io.core.Input -import io.ktor.utils.io.core.Output +import kotlinx.io.Sink +import kotlinx.io.Source +import kotlinx.io.bytestring.ByteString +import kotlinx.io.bytestring.encodeToByteString +import kotlinx.io.readByteString +import kotlinx.io.writeString import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Global import space.kscience.dataforge.io.* @@ -15,49 +19,49 @@ public class FrontMatterEnvelopeFormat( private val metaFormatFactory: MetaFormatFactory = YamlMetaFormat, ) : EnvelopeFormat { - override fun readObject(binary: Binary): Envelope = binary.read { + override fun readFrom(binary: Binary): Envelope = binary.read { var offset = 0 offset += discardWithSeparator( - SEPARATOR.encodeToByteArray(), + SEPARATOR, atMost = 1024, ) val line = ByteArray { - offset += readWithSeparatorTo(this, "\n".encodeToByteArray()) + offset += readWithSeparatorTo(this, "\n".encodeToByteString()) }.decodeToString() val readMetaFormat = line.trim().takeIf { it.isNotBlank() }?.let { io.resolveMetaFormat(it) } ?: YamlMetaFormat val packet = ByteArray { - offset += readWithSeparatorTo(this, SEPARATOR.encodeToByteArray()) + offset += readWithSeparatorTo(this, SEPARATOR) } offset += discardLine() - val meta = readMetaFormat.readObject(packet.asBinary()) + val meta = readMetaFormat.readFrom(packet.asBinary()) Envelope(meta, binary.view(offset)) } - override fun readObject(input: Input): Envelope = readObject(input.readBinary()) + override fun readFrom(source: Source): Envelope = readFrom(source.readBinary()) - override fun writeObject( - output: Output, + override fun writeTo( + sink: Sink, obj: Envelope, ) { val metaFormat = metaFormatFactory.build(io.context, meta) val formatSuffix = if (metaFormat is YamlMetaFormat) "" else metaFormatFactory.shortName - output.writeRawString("$SEPARATOR${formatSuffix}\r\n") - metaFormat.run { metaFormat.writeObject(output, obj.meta) } - output.writeRawString("$SEPARATOR\r\n") + sink.writeString("$SEPARATOR${formatSuffix}\r\n") + metaFormat.run { metaFormat.writeTo(sink, obj.meta) } + sink.writeString("$SEPARATOR\r\n") //Printing data obj.data?.let { data -> - output.writeBinary(data) + sink.writeBinary(data) } } public companion object : EnvelopeFormatFactory { - public const val SEPARATOR: String = "---" + public val SEPARATOR: ByteString = "---".encodeToByteString() private val metaTypeRegex = "---(\\w*)\\s*".toRegex() @@ -69,8 +73,8 @@ public class FrontMatterEnvelopeFormat( override fun peekFormat(io: IOPlugin, binary: Binary): EnvelopeFormat? = binary.read { //read raw string to avoid UTF issues - val line = readRawString(3) - return@read if (line == "---") { + val line = readByteString(3) + return@read if (line == "---".encodeToByteString()) { default } else { null @@ -79,15 +83,15 @@ public class FrontMatterEnvelopeFormat( private val default by lazy { build(Global, Meta.EMPTY) } - override fun readObject(binary: Binary): Envelope = default.readObject(binary) + override fun readFrom(binary: Binary): Envelope = default.readFrom(binary) - override fun writeObject( - output: Output, + override fun writeTo( + sink: Sink, obj: Envelope, - ): Unit = default.writeObject(output, obj) + ): Unit = default.writeTo(sink, obj) - override fun readObject(input: Input): Envelope = default.readObject(input) + override fun readFrom(source: Source): Envelope = default.readFrom(source) } } \ No newline at end of file diff --git a/dataforge-io/dataforge-io-yaml/src/commonMain/kotlin/space/kscience/dataforge/io/yaml/YamlMetaFormat.kt b/dataforge-io/dataforge-io-yaml/src/commonMain/kotlin/space/kscience/dataforge/io/yaml/YamlMetaFormat.kt index 51c143a6..7c4c1246 100644 --- a/dataforge-io/dataforge-io-yaml/src/commonMain/kotlin/space/kscience/dataforge/io/yaml/YamlMetaFormat.kt +++ b/dataforge-io/dataforge-io-yaml/src/commonMain/kotlin/space/kscience/dataforge/io/yaml/YamlMetaFormat.kt @@ -1,13 +1,13 @@ package space.kscience.dataforge.io.yaml -import io.ktor.utils.io.core.Input -import io.ktor.utils.io.core.Output +import kotlinx.io.Sink +import kotlinx.io.Source +import kotlinx.io.readString +import kotlinx.io.writeString import net.mamoe.yamlkt.* import space.kscience.dataforge.context.Context import space.kscience.dataforge.io.MetaFormat import space.kscience.dataforge.io.MetaFormatFactory -import space.kscience.dataforge.io.readUtf8String -import space.kscience.dataforge.io.writeUtf8String import space.kscience.dataforge.meta.* import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.get @@ -32,7 +32,7 @@ public fun Meta.toYaml(): YamlMap { private class YamlMeta(private val yamlMap: YamlMap, private val descriptor: MetaDescriptor? = null) : Meta { override val value: Value? - get() = yamlMap.getStringOrNull(null)?.parseValue() + get() = yamlMap.getStringOrNull(null)?.let { Value.parse(it) } private fun buildItems(): Map { val map = LinkedHashMap() @@ -43,13 +43,13 @@ private class YamlMeta(private val yamlMap: YamlMap, private val descriptor: Met val token = NameToken(stringKey) when (value) { YamlNull -> Meta(Null) - is YamlLiteral -> map[token] = Meta(value.content.parseValue()) + is YamlLiteral -> map[token] = Meta(Value.parse(value.content)) is YamlMap -> map[token] = value.toMeta() is YamlList -> if (value.all { it is YamlLiteral }) { val listValue = ListValue( value.map { //We already checked that all values are primitives - (it as YamlLiteral).content.parseValue() + Value.parse((it as YamlLiteral).content) } ) map[token] = Meta(listValue) @@ -75,7 +75,7 @@ private class YamlMeta(private val yamlMap: YamlMap, private val descriptor: Met public fun YamlElement.toMeta(descriptor: MetaDescriptor? = null): Meta = when (this) { YamlNull -> Meta(Null) - is YamlLiteral -> Meta(content.parseValue()) + is YamlLiteral -> Meta(Value.parse(content)) is YamlMap -> toMeta() //We can't return multiple items therefore we create top level node is YamlList -> YamlMap(mapOf("@yamlArray" to this)).toMeta(descriptor) @@ -89,14 +89,14 @@ public fun YamlMap.toMeta(): Meta = YamlMeta(this) */ public class YamlMetaFormat(private val meta: Meta) : MetaFormat { - override fun writeMeta(output: Output, meta: Meta, descriptor: MetaDescriptor?) { + override fun writeMeta(sink: Sink, meta: Meta, descriptor: MetaDescriptor?) { val yaml: YamlMap = meta.toYaml() val string = Yaml.encodeToString(YamlMap.serializer(), yaml) - output.writeUtf8String(string) + sink.writeString(string) } - override fun readMeta(input: Input, descriptor: MetaDescriptor?): Meta { - val yaml = Yaml.decodeYamlMapFromString(input.readUtf8String()) + override fun readMeta(source: Source, descriptor: MetaDescriptor?): Meta { + val yaml = Yaml.decodeYamlMapFromString(source.readString()) return yaml.toMeta() } @@ -109,10 +109,10 @@ public class YamlMetaFormat(private val meta: Meta) : MetaFormat { private val default = YamlMetaFormat(Meta.EMPTY) - override fun writeMeta(output: Output, meta: Meta, descriptor: MetaDescriptor?): Unit = - default.writeMeta(output, meta, descriptor) + override fun writeMeta(sink: Sink, meta: Meta, descriptor: MetaDescriptor?): Unit = + default.writeMeta(sink, meta, descriptor) - override fun readMeta(input: Input, descriptor: MetaDescriptor?): Meta = - default.readMeta(input, descriptor) + override fun readMeta(source: Source, descriptor: MetaDescriptor?): Meta = + default.readMeta(source, descriptor) } } \ No newline at end of file diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/Binary.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/Binary.kt index bcc20064..f85dd98e 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/Binary.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/Binary.kt @@ -1,6 +1,9 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.core.* +import kotlinx.io.Sink +import kotlinx.io.Source +import kotlinx.io.buffered +import kotlinx.io.readByteArray import kotlin.math.min /** @@ -17,13 +20,13 @@ public interface Binary { * Read maximum of [atMost] bytes as input from the binary, starting at [offset]. The generated input is always closed * when leaving scope, so it could not be leaked outside of scope of [block]. */ - public fun read(offset: Int = 0, atMost: Int = size - offset, block: Input.() -> R): R + public fun read(offset: Int = 0, atMost: Int = size - offset, block: Source.() -> R): R - public suspend fun readSuspend(offset: Int = 0, atMost: Int = size - offset, block: suspend Input.() -> R): R + public suspend fun readSuspend(offset: Int = 0, atMost: Int = size - offset, block: suspend Source.() -> R): R /** * Read a binary with given [offset] relative to this binary and given [binarySize]. - * In general, resulting binary is of the same type as this one, but it is not guaranteed. + * In general, the resulting binary is of the same type as this one, but it is not guaranteed. */ public fun view(offset: Int, binarySize: Int = size - offset): Binary @@ -38,25 +41,27 @@ internal class ByteArrayBinary( override val size: Int = array.size - start, ) : Binary { - override fun read(offset: Int, atMost: Int, block: Input.() -> R): R { + override fun read(offset: Int, atMost: Int, block: Source.() -> R): R { require(offset >= 0) { "Offset must be positive" } require(offset < array.size) { "Offset $offset is larger than array size" } - val input = ByteReadPacket( + + return ByteArraySource( array, offset + start, min(atMost, size - offset) - ) - return input.use(block) + ).buffered().use(block) } - override suspend fun readSuspend(offset: Int, atMost: Int, block: suspend Input.() -> R): R { + override suspend fun readSuspend(offset: Int, atMost: Int, block: suspend Source.() -> R): R { require(offset >= 0) { "Offset must be positive" } require(offset < array.size) { "Offset $offset is larger than array size" } - val input = ByteReadPacket( + + val input = ByteArraySource( array, offset + start, min(atMost, size - offset) - ) + ).buffered() + return try { block(input) } finally { @@ -77,26 +82,26 @@ public fun Binary.toByteArray(): ByteArray = if (this is ByteArrayBinary) { array.copyOfRange(start, start + size) // TODO do we need to ensure data safety here? } else { read { - readBytes() + readByteArray() } } //TODO optimize for file-based Inputs -public fun Input.readBinary(size: Int? = null): Binary { - val array = if (size == null) readBytes() else readBytes(size) +public fun Source.readBinary(size: Int? = null): Binary { + val array = if (size == null) readByteArray() else readByteArray(size) return ByteArrayBinary(array) } /** * Direct write of binary to the output. Returns the number of bytes written */ -public fun Output.writeBinary(binary: Binary): Int { +public fun Sink.writeBinary(binary: Binary): Int { return if (binary is ByteArrayBinary) { - writeFully(binary.array, binary.start, binary.start + binary.size) + write(binary.array, binary.start, binary.start + binary.size) binary.size } else { binary.read { - copyTo(this@writeBinary).toInt() + transferTo(this@writeBinary).toInt() } } } \ No newline at end of file diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeBuilder.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeBuilder.kt index eedd2075..e38df146 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeBuilder.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeBuilder.kt @@ -1,6 +1,6 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.core.Output +import kotlinx.io.Sink import space.kscience.dataforge.meta.* public class EnvelopeBuilder : Envelope { @@ -33,7 +33,7 @@ public class EnvelopeBuilder : Envelope { /** * Construct a data binary from given builder */ - public inline fun data(block: Output.() -> Unit) { + public inline fun data(block: Sink.() -> Unit) { data = ByteArray { block() }.asBinary() } diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeFormat.kt index 28b59abb..0df5ab27 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeFormat.kt @@ -1,10 +1,10 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.core.Input +import kotlinx.io.Source import space.kscience.dataforge.context.Context import space.kscience.dataforge.io.EnvelopeFormatFactory.Companion.ENVELOPE_FORMAT_TYPE import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.misc.Type +import space.kscience.dataforge.misc.DfId import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import kotlin.reflect.KType @@ -15,9 +15,9 @@ public interface EnvelopeFormat : IOFormat { override val type: KType get() = typeOf() } -public fun EnvelopeFormat.read(input: Input): Envelope = readObject(input) +public fun EnvelopeFormat.read(input: Source): Envelope = readFrom(input) -@Type(ENVELOPE_FORMAT_TYPE) +@DfId(ENVELOPE_FORMAT_TYPE) public interface EnvelopeFormatFactory : IOFormatFactory, EnvelopeFormat { override val type: KType get() = typeOf() diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeParts.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeParts.kt index 248ecf19..183e7b03 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeParts.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeParts.kt @@ -1,5 +1,8 @@ package space.kscience.dataforge.io +import kotlinx.io.bytestring.ByteString +import kotlinx.io.bytestring.decodeToString +import kotlinx.io.write import space.kscience.dataforge.io.Envelope.Companion.ENVELOPE_NODE_KEY import space.kscience.dataforge.io.PartDescriptor.Companion.DEFAULT_MULTIPART_DATA_SEPARATOR import space.kscience.dataforge.io.PartDescriptor.Companion.MULTIPART_DATA_TYPE @@ -20,7 +23,7 @@ private class PartDescriptor : Scheme() { val PARTS_KEY = MULTIPART_KEY + "parts" val SEPARATOR_KEY = MULTIPART_KEY + "separator" - const val DEFAULT_MULTIPART_DATA_SEPARATOR = "\r\n#~PART~#\r\n" + val DEFAULT_MULTIPART_DATA_SEPARATOR = "\r\n#~PART~#\r\n".toAsciiByteString() const val MULTIPART_DATA_TYPE = "envelope.multipart" } @@ -32,12 +35,12 @@ public typealias EnvelopeParts = List public fun EnvelopeBuilder.multipart( parts: EnvelopeParts, - separator: String = DEFAULT_MULTIPART_DATA_SEPARATOR, + separator: ByteString = DEFAULT_MULTIPART_DATA_SEPARATOR, ) { dataType = MULTIPART_DATA_TYPE var offsetCounter = 0 - val separatorSize = separator.length + val separatorSize = separator.size val partDescriptors = parts.map { (binary, description) -> offsetCounter += separatorSize PartDescriptor { @@ -51,14 +54,14 @@ public fun EnvelopeBuilder.multipart( meta { if (separator != DEFAULT_MULTIPART_DATA_SEPARATOR) { - SEPARATOR_KEY put separator + SEPARATOR_KEY put separator.decodeToString() } setIndexed(PARTS_KEY, partDescriptors.map { it.toMeta() }) } data { parts.forEach { - writeRawString(separator) + write(separator) writeBinary(it.binary) } } @@ -69,7 +72,7 @@ public fun EnvelopeBuilder.multipart( */ public fun EnvelopeBuilder.envelopes( envelopes: List, - separator: String = DEFAULT_MULTIPART_DATA_SEPARATOR, + separator: ByteString = DEFAULT_MULTIPART_DATA_SEPARATOR, ) { val parts = envelopes.map { val binary = Binary(it, TaggedEnvelopeFormat) diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/IOFormat.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/IOFormat.kt index 12ea587b..ffcadf1a 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/IOFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/IOFormat.kt @@ -1,12 +1,14 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.core.* +import kotlinx.io.Sink +import kotlinx.io.Source +import kotlinx.io.readByteArray import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Factory import space.kscience.dataforge.io.IOFormatFactory.Companion.IO_FORMAT_TYPE import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.misc.DfId import space.kscience.dataforge.misc.Named -import space.kscience.dataforge.misc.Type import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import kotlin.reflect.KType @@ -21,9 +23,9 @@ public interface IOReader { */ public val type: KType - public fun readObject(input: Input): T + public fun readFrom(source: Source): T - public fun readObject(binary: Binary): T = binary.read { readObject(this) } + public fun readFrom(binary: Binary): T = binary.read { readFrom(this) } public companion object { /** @@ -32,21 +34,21 @@ public interface IOReader { public val binary: IOReader = object : IOReader { override val type: KType = typeOf() - override fun readObject(input: Input): Binary = input.readBytes().asBinary() + override fun readFrom(source: Source): Binary = source.readByteArray().asBinary() - override fun readObject(binary: Binary): Binary = binary + override fun readFrom(binary: Binary): Binary = binary } } } -public inline fun IOReader(crossinline read: Input.() -> T): IOReader = object : IOReader { +public inline fun IOReader(crossinline read: Source.() -> T): IOReader = object : IOReader { override val type: KType = typeOf() - override fun readObject(input: Input): T = input.read() + override fun readFrom(source: Source): T = source.read() } public fun interface IOWriter { - public fun writeObject(output: Output, obj: T) + public fun writeTo(sink: Sink, obj: T) } /** @@ -54,24 +56,23 @@ public fun interface IOWriter { */ public interface IOFormat : IOReader, IOWriter -public fun Input.readObject(format: IOReader): T = format.readObject(this@readObject) +public fun Source.readWith(format: IOReader): T = format.readFrom(this) -public fun IOFormat.readObjectFrom(binary: Binary): T = binary.read { - readObject(this) +/** + * Read given binary as an object using given format + */ +public fun Binary.readWith(format: IOReader): T = read { + readWith(format) } /** - * Read given binary as object using given format + * Write an object to the [Sink] with given [format] */ -public fun Binary.readWith(format: IOReader): T = read { - readObject(format) -} - -public fun Output.writeObject(format: IOWriter, obj: T): Unit = - format.writeObject(this@writeObject, obj) +public fun Sink.writeWith(format: IOWriter, obj: T): Unit = + format.writeTo(this, obj) -@Type(IO_FORMAT_TYPE) +@DfId(IO_FORMAT_TYPE) public interface IOFormatFactory : Factory>, Named { /** * Explicit type for dynamic type checks @@ -85,18 +86,33 @@ public interface IOFormatFactory : Factory>, Named { } } -public fun Binary(obj: T, format: IOWriter): Binary = Binary { format.writeObject(this, obj) } +public fun Binary(obj: T, format: IOWriter): Binary = Binary { format.writeTo(this, obj) } + +public object FloatIOFormat : IOFormat, IOFormatFactory { + override fun build(context: Context, meta: Meta): IOFormat = this + + override val name: Name = "float32".asName() + + override val type: KType get() = typeOf() + + override fun writeTo(sink: Sink, obj: Float) { + sink.writeFloat(obj) + } + + override fun readFrom(source: Source): Float = source.readFloat() +} + public object DoubleIOFormat : IOFormat, IOFormatFactory { override fun build(context: Context, meta: Meta): IOFormat = this - override val name: Name = "double".asName() + override val name: Name = "float64".asName() override val type: KType get() = typeOf() - override fun writeObject(output: Output, obj: Double) { - output.writeDouble(obj) + override fun writeTo(sink: Sink, obj: Double) { + sink.writeLong(obj.toBits()) } - override fun readObject(input: Input): Double = input.readDouble() + override fun readFrom(source: Source): Double = source.readDouble() } \ No newline at end of file diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/JsonMetaFormat.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/JsonMetaFormat.kt index f3d9e02a..effc3b12 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/JsonMetaFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/JsonMetaFormat.kt @@ -1,10 +1,10 @@ -@file:Suppress("UNUSED_PARAMETER") - package space.kscience.dataforge.io -import io.ktor.utils.io.core.Input -import io.ktor.utils.io.core.Output +import kotlinx.io.Sink +import kotlinx.io.Source +import kotlinx.io.readString +import kotlinx.io.writeString import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonElement import space.kscience.dataforge.context.Context @@ -18,13 +18,13 @@ import space.kscience.dataforge.meta.toMeta */ public class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat { - override fun writeMeta(output: Output, meta: Meta, descriptor: MetaDescriptor?) { + override fun writeMeta(sink: Sink, meta: Meta, descriptor: MetaDescriptor?) { val jsonElement = meta.toJson(descriptor) - output.writeUtf8String(json.encodeToString(JsonElement.serializer(), jsonElement)) + sink.writeString(json.encodeToString(JsonElement.serializer(), jsonElement)) } - override fun readMeta(input: Input, descriptor: MetaDescriptor?): Meta { - val str = input.readUtf8String()//readByteArray().decodeToString() + override fun readMeta(source: Source, descriptor: MetaDescriptor?): Meta { + val str = source.readString() val jsonElement = json.parseToJsonElement(str) return jsonElement.toMeta(descriptor) } @@ -39,10 +39,10 @@ public class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat private val default = JsonMetaFormat() - override fun writeMeta(output: Output, meta: Meta, descriptor: MetaDescriptor?): Unit = - default.run { writeMeta(output, meta, descriptor) } + override fun writeMeta(sink: Sink, meta: Meta, descriptor: MetaDescriptor?): Unit = + default.run { writeMeta(sink, meta, descriptor) } - override fun readMeta(input: Input, descriptor: MetaDescriptor?): Meta = - default.run { readMeta(input, descriptor) } + override fun readMeta(source: Source, descriptor: MetaDescriptor?): Meta = + default.run { readMeta(source, descriptor) } } } diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/MetaFormat.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/MetaFormat.kt index c902c2e6..cadf87ca 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/MetaFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/MetaFormat.kt @@ -1,15 +1,15 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.Input -import io.ktor.utils.io.core.Output -import io.ktor.utils.io.core.use + +import kotlinx.io.Sink +import kotlinx.io.Source +import kotlinx.io.buffered import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Global import space.kscience.dataforge.io.MetaFormatFactory.Companion.META_FORMAT_TYPE import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.descriptors.MetaDescriptor -import space.kscience.dataforge.misc.Type +import space.kscience.dataforge.misc.DfId import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.plus @@ -23,22 +23,22 @@ public interface MetaFormat : IOFormat { override val type: KType get() = typeOf() - override fun writeObject(output: Output, obj: Meta) { - writeMeta(output, obj, null) + override fun writeTo(sink: Sink, obj: Meta) { + writeMeta(sink, obj, null) } - override fun readObject(input: Input): Meta = readMeta(input) + override fun readFrom(source: Source): Meta = readMeta(source) public fun writeMeta( - output: Output, + sink: Sink, meta: Meta, descriptor: MetaDescriptor? = null, ) - public fun readMeta(input: Input, descriptor: MetaDescriptor? = null): Meta + public fun readMeta(source: Source, descriptor: MetaDescriptor? = null): Meta } -@Type(META_FORMAT_TYPE) +@DfId(META_FORMAT_TYPE) public interface MetaFormatFactory : IOFormatFactory, MetaFormat { public val shortName: String @@ -57,15 +57,13 @@ public interface MetaFormatFactory : IOFormatFactory, MetaFormat { public fun Meta.toString(format: MetaFormat): String = ByteArray { format.run { - writeObject(this@ByteArray, this@toString) + writeTo(this@ByteArray, this@toString) } }.decodeToString() public fun Meta.toString(formatFactory: MetaFormatFactory): String = toString(formatFactory.build(Global, Meta.EMPTY)) -public fun MetaFormat.parse(str: String): Meta { - return ByteReadPacket(str.encodeToByteArray()).use { readObject(it) } -} +public fun MetaFormat.parse(str: String): Meta = readFrom(StringSource(str).buffered()) public fun MetaFormatFactory.parse(str: String, formatMeta: Meta): Meta = build(Global, formatMeta).parse(str) diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/TaggedEnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/TaggedEnvelopeFormat.kt index a320837d..13b14595 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/TaggedEnvelopeFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/TaggedEnvelopeFormat.kt @@ -1,6 +1,7 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.core.* +import kotlinx.io.* +import kotlinx.io.bytestring.decodeToString import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Global import space.kscience.dataforge.meta.Meta @@ -18,7 +19,7 @@ import space.kscience.dataforge.names.plus public class TaggedEnvelopeFormat( public val io: IOPlugin, public val version: VERSION = VERSION.DF02, - public val metaFormatFactory: MetaFormatFactory = JsonMetaFormat + public val metaFormatFactory: MetaFormatFactory = JsonMetaFormat, ) : EnvelopeFormat { // private val metaFormat = io.metaFormat(metaFormatKey) @@ -26,59 +27,60 @@ public class TaggedEnvelopeFormat( private fun Tag.toBinary() = Binary { - writeRawString(START_SEQUENCE) - writeRawString(version.name) + write(START_SEQUENCE) + writeString(version.name) writeShort(metaFormatKey) writeUInt(metaSize) when (version) { VERSION.DF02 -> { writeUInt(dataSize.toUInt()) } + VERSION.DF03 -> { writeULong(dataSize) } } - writeRawString(END_SEQUENCE) + write(END_SEQUENCE) } - override fun writeObject( - output: Output, + override fun writeTo( + sink: Sink, obj: Envelope, ) { val metaFormat = metaFormatFactory.build(io.context, Meta.EMPTY) - val metaBytes = Binary(obj.meta,metaFormat) + val metaBytes = Binary(obj.meta, metaFormat) val actualSize: ULong = (obj.data?.size ?: 0).toULong() val tag = Tag(metaFormatFactory.key, metaBytes.size.toUInt() + 2u, actualSize) - output.writeBinary(tag.toBinary()) - output.writeBinary(metaBytes) - output.writeRawString("\r\n") + sink.writeBinary(tag.toBinary()) + sink.writeBinary(metaBytes) + sink.writeString("\r\n") obj.data?.let { - output.writeBinary(it) + sink.writeBinary(it) } } /** * Read an envelope from input into memory * - * @param input an input to read from + * @param source an input to read from * @param formats a collection of meta formats to resolve */ - override fun readObject(input: Input): Envelope { - val tag = input.readTag(this.version) + override fun readFrom(source: Source): Envelope { + val tag = source.readTag(this.version) val metaFormat = io.resolveMetaFormat(tag.metaFormatKey) ?: error("Meta format with key ${tag.metaFormatKey} not found") - val metaBinary = input.readBinary(tag.metaSize.toInt()) + val metaBinary = source.readBinary(tag.metaSize.toInt()) - val meta: Meta = metaFormat.readObjectFrom(metaBinary) + val meta: Meta = metaFormat.readFrom(metaBinary) - val data = input.readBinary(tag.dataSize.toInt()) + val data = source.readBinary(tag.dataSize.toInt()) return SimpleEnvelope(meta, data) } - override fun readObject(binary: Binary): Envelope = binary.read{ + override fun readFrom(binary: Binary): Envelope = binary.read { val tag = readTag(version) val metaFormat = io.resolveMetaFormat(tag.metaFormatKey) @@ -86,7 +88,7 @@ public class TaggedEnvelopeFormat( val metaBinary = readBinary(tag.metaSize.toInt()) - val meta: Meta = metaFormat.readObjectFrom(metaBinary) + val meta: Meta = metaFormat.readFrom(metaBinary) SimpleEnvelope(meta, binary.view((version.tagSize + tag.metaSize).toInt(), tag.dataSize.toInt())) @@ -104,8 +106,8 @@ public class TaggedEnvelopeFormat( } public companion object : EnvelopeFormatFactory { - private const val START_SEQUENCE = "#~" - private const val END_SEQUENCE = "~#\r\n" + private val START_SEQUENCE = "#~".toAsciiByteString() + private val END_SEQUENCE = "~#\r\n".toAsciiByteString() override val name: Name = EnvelopeFormatFactory.ENVELOPE_FACTORY_NAME + "tagged" @@ -121,53 +123,48 @@ public class TaggedEnvelopeFormat( return TaggedEnvelopeFormat(io, version) } - private fun Input.readTag(version: VERSION): Tag { - val start = readRawString(2) + private fun Source.readTag(version: VERSION): Tag { + val start = readByteString(2) if (start != START_SEQUENCE) error("The input is not an envelope") - val versionString = readRawString(4) - if (version.name != versionString) error("Wrong version of DataForge: expected $version but found $versionString") + val versionString = readByteString(4) + if (version.name.toAsciiByteString() != versionString) error("Wrong version of DataForge: expected $version but found $versionString") val metaFormatKey = readShort() val metaLength = readUInt() val dataLength: ULong = when (version) { VERSION.DF02 -> readUInt().toULong() VERSION.DF03 -> readULong() } - val end = readRawString(4) + val end = readByteString(4) if (end != END_SEQUENCE) error("The input is not an envelope") return Tag(metaFormatKey, metaLength, dataLength) } - override fun peekFormat(io: IOPlugin, binary: Binary): EnvelopeFormat? { - return try { - binary.read { - val header = readRawString(6) - return@read when (header.substring(2..5)) { - VERSION.DF02.name -> TaggedEnvelopeFormat(io, VERSION.DF02) - VERSION.DF03.name -> TaggedEnvelopeFormat(io, VERSION.DF03) - else -> null - } + override fun peekFormat(io: IOPlugin, binary: Binary): EnvelopeFormat? = try { + binary.read { + val header = readByteString(6) + when (header.substring(2, 6).decodeToString()) { + VERSION.DF02.name -> TaggedEnvelopeFormat(io, VERSION.DF02) + VERSION.DF03.name -> TaggedEnvelopeFormat(io, VERSION.DF03) + else -> null } - } catch (ex: Exception) { - null } + } catch (ex: Exception) { + null } private val default by lazy { build(Global, Meta.EMPTY) } - override fun readObject(binary: Binary): Envelope = - default.run { readObject(binary) } + override fun readFrom(binary: Binary): Envelope = + default.run { readFrom(binary) } - override fun writeObject( - output: Output, + override fun writeTo( + sink: Sink, obj: Envelope, ): Unit = default.run { - writeObject( - output, - obj, - ) + writeTo(sink, obj) } - override fun readObject(input: Input): Envelope = default.readObject(input) + override fun readFrom(source: Source): Envelope = default.readFrom(source) } } \ No newline at end of file diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/TaglessEnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/TaglessEnvelopeFormat.kt index e6dc054f..011aa2c6 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/TaglessEnvelopeFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/TaglessEnvelopeFormat.kt @@ -1,9 +1,9 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.Input -import io.ktor.utils.io.core.Output -import io.ktor.utils.io.core.readUTF8UntilDelimiterTo + +import kotlinx.io.* +import kotlinx.io.bytestring.ByteString +import kotlinx.io.bytestring.encodeToByteString import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Global import space.kscience.dataforge.meta.Meta @@ -28,35 +28,36 @@ public class TaglessEnvelopeFormat( // writeFully("#? $key: $value;\r\n".encodeToByteArray()) // } - override fun writeObject( - output: Output, + override fun writeTo( + sink: Sink, obj: Envelope, ) { val metaFormat = metaFormatFactory.build(this.io.context, meta) //printing header - output.writeRawString(TAGLESS_ENVELOPE_HEADER + "\r\n") + sink.write(TAGLESS_ENVELOPE_HEADER) + sink.writeString("\r\n") //Printing meta if (!obj.meta.isEmpty()) { val metaBinary = Binary(obj.meta, metaFormat) - output.writeUtf8String(META_START + "-${metaFormatFactory.shortName}\r\n") - output.writeBinary(metaBinary) - output.writeRawString("\r\n") + sink.writeString(META_START + "-${metaFormatFactory.shortName}\r\n") + sink.writeBinary(metaBinary) + sink.writeString("\r\n") } //Printing data obj.data?.let { data -> //val actualSize: Int = envelope.data?.size ?: 0 - output.writeUtf8String(DATA_START + "\r\n") - output.writeBinary(data) + sink.writeString(DATA_START + "\r\n") + sink.writeBinary(data) } } - override fun readObject(input: Input): Envelope { + override fun readFrom(source: Source): Envelope { //read preamble - input.discardWithSeparator( - TAGLESS_ENVELOPE_HEADER.encodeToByteArray(), + source.discardWithSeparator( + TAGLESS_ENVELOPE_HEADER, atMost = 1024, ) @@ -64,22 +65,22 @@ public class TaglessEnvelopeFormat( var data: Binary? = null - input.discardWithSeparator( + source.discardWithSeparator( SEPARATOR_PREFIX, atMost = 1024, ) var header: String = ByteArray { - input.readUTF8UntilDelimiterTo(this, "\n") + source.readWithSeparatorTo(this, "\n".encodeToByteString()) }.decodeToString() - while (!input.endOfInput) { + while (!source.exhausted()) { val block = ByteArray { - input.readWithSeparatorTo(this, SEPARATOR_PREFIX) + source.readWithSeparatorTo(this, SEPARATOR_PREFIX) } val nextHeader = ByteArray { - input.readWithSeparatorTo(this, "\n".encodeToByteArray()) + source.readWithSeparatorTo(this, "\n".encodeToByteString()) }.decodeToString() //terminate on end @@ -89,7 +90,7 @@ public class TaglessEnvelopeFormat( if (header.startsWith("META")) { //TODO check format val metaFormat: MetaFormatFactory = JsonMetaFormat - meta = metaFormat.readMeta(ByteReadPacket(block)) + meta = metaFormat.readMeta(ByteArraySource(block).buffered()) } if (header.startsWith("DATA")) { @@ -111,9 +112,9 @@ public class TaglessEnvelopeFormat( public const val TAGLESS_ENVELOPE_TYPE: String = "tagless" - public val SEPARATOR_PREFIX: ByteArray = "\n#~".encodeToByteArray() + public val SEPARATOR_PREFIX: ByteString = "\n#~".encodeToByteString() - public const val TAGLESS_ENVELOPE_HEADER: String = "#~DFTL" + public val TAGLESS_ENVELOPE_HEADER: ByteString = "#~DFTL".encodeToByteString() // public const val META_START_PROPERTY: String = "metaSeparator" public const val META_START: String = "#~META" @@ -131,24 +132,21 @@ public class TaglessEnvelopeFormat( private val default by lazy { build(Global, Meta.EMPTY) } - override fun readObject(binary: Binary): Envelope = default.run { readObject(binary) } + override fun readFrom(binary: Binary): Envelope = default.run { readFrom(binary) } - override fun writeObject( - output: Output, + override fun writeTo( + sink: Sink, obj: Envelope, ): Unit = default.run { - writeObject( - output, - obj, - ) + writeTo(sink, obj) } - override fun readObject(input: Input): Envelope = default.readObject(input) + override fun readFrom(source: Source): Envelope = default.readFrom(source) override fun peekFormat(io: IOPlugin, binary: Binary): EnvelopeFormat? { return try { binary.read { - val string = readRawString(TAGLESS_ENVELOPE_HEADER.length) + val string = readByteString(TAGLESS_ENVELOPE_HEADER.size) return@read if (string == TAGLESS_ENVELOPE_HEADER) { TaglessEnvelopeFormat(io) } else { diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/ioMisc.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/ioMisc.kt index ad03ba6e..93fd210a 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/ioMisc.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/ioMisc.kt @@ -1,40 +1,41 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.bits.Memory -import io.ktor.utils.io.charsets.Charsets -import io.ktor.utils.io.charsets.decodeExactBytes -import io.ktor.utils.io.core.* -import io.ktor.utils.io.core.internal.ChunkBuffer +import kotlinx.io.* +import kotlinx.io.bytestring.ByteString +import kotlinx.io.bytestring.decodeToString +import kotlinx.io.bytestring.encodeToByteString import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.misc.DFExperimental +import kotlin.math.min -public fun Output.writeRawString(str: String) { - writeFully(str.toByteArray(Charsets.ISO_8859_1)) +/** + * Convert a string literal, containing only ASCII characters to a [ByteString]. + * Throws an error if there are non-ASCII characters. + */ +public fun String.toAsciiByteString(): ByteString { + val bytes = ByteArray(length) { + val char = get(it) + val code = char.code + if (code > Byte.MAX_VALUE) error("Symbol $char is not ASCII symbol") else code.toByte() + } + return ByteString(bytes) } -public fun Output.writeUtf8String(str: String) { - writeFully(str.encodeToByteArray()) -} +public inline fun Buffer(block: Sink.() -> Unit): Buffer = Buffer().apply(block) -public fun Input.readRawString(size: Int): String { - return Charsets.ISO_8859_1.newDecoder().decodeExactBytes(this, size) -} +//public fun Source.readSafeUtf8Line(): String = readUTF8Line() ?: error("Line not found") -public fun Input.readUtf8String(): String = readBytes().decodeToString() +public inline fun ByteArray(block: Sink.() -> Unit): ByteArray = + Buffer(block).readByteArray() -public fun Input.readSafeUtf8Line(): String = readUTF8Line() ?: error("Line not found") - -public inline fun ByteArray(block: Output.() -> Unit): ByteArray = - buildPacket(block).readBytes() - -public inline fun Binary(block: Output.() -> Unit): Binary = +public inline fun Binary(block: Sink.() -> Unit): Binary = ByteArray(block).asBinary() public operator fun Binary.get(range: IntRange): Binary = view(range.first, range.last - range.first) /** * Return inferred [EnvelopeFormat] if only one format could read given file. If no format accepts the binary, return null. If - * multiple formats accepts binary, throw an error. + * multiple formats accept binary, throw an error. */ public fun IOPlugin.peekBinaryEnvelopeFormat(binary: Binary): EnvelopeFormat? { val formats = envelopeFormatFactories.mapNotNull { factory -> @@ -56,7 +57,7 @@ public fun IOPlugin.readEnvelope( binary: Binary, readNonEnvelopes: Boolean = false, formatPicker: IOPlugin.(Binary) -> EnvelopeFormat? = IOPlugin::peekBinaryEnvelopeFormat, -): Envelope = formatPicker(binary)?.readObject(binary) ?: if (readNonEnvelopes) { +): Envelope = formatPicker(binary)?.readFrom(binary) ?: if (readNonEnvelopes) { // if no format accepts file, read it as binary Envelope(Meta.EMPTY, binary) } else error("Can't infer format for $binary") @@ -96,74 +97,139 @@ private class RingByteArray( else -> inputArray.indices.all { inputArray[it] == get(it) } } + fun contentEquals(byteString: ByteString): Boolean = when { + byteString.size != buffer.size -> false + size < buffer.size -> false + else -> (0 until byteString.size).all { byteString[it] == get(it) } + } + } private fun RingByteArray.toArray(): ByteArray = ByteArray(size) { get(it) } /** - * Read [Input] into [output] until designated multibyte [separator] and optionally continues until + * Read [Source] into [output] until designated multibyte [separator] and optionally continues until * the end of the line after it. Throw error if [separator] not found and [atMost] bytes are read. * Also fails if [separator] not found until the end of input. * - * Separator itself is not read into Output. + * The Separator itself is not read into [Sink]. * * @param errorOnEof if true error is thrown if separator is never encountered * * @return bytes actually being read, including separator */ -public fun Input.readWithSeparatorTo( - output: Output, - separator: ByteArray, +public fun Source.readWithSeparatorTo( + output: Sink?, + separator: ByteString, atMost: Int = Int.MAX_VALUE, errorOnEof: Boolean = false, ): Int { var counter = 0 val rb = RingByteArray(ByteArray(separator.size)) - takeWhile { buffer -> - while (buffer.canRead()) { - val byte = buffer.readByte() - counter++ - if (counter >= atMost) error("Maximum number of bytes to be read $atMost reached.") - rb.push(byte) - if (rb.contentEquals(separator)) { - return counter - } else if (rb.isFull()) { - output.writeByte(rb[0]) - } + + while (!exhausted()) { + val byte = readByte() + counter++ + if (counter >= atMost) error("Maximum number of bytes to be read $atMost reached.") + rb.push(byte) + if (rb.contentEquals(separator)) { + return counter + } else if (rb.isFull()) { + output?.writeByte(rb[0]) } - !endOfInput } + if (errorOnEof) { error("Read to the end of input without encountering ${separator.decodeToString()}") } else { - for(i in 1 until rb.size){ - output.writeByte(rb[i]) + for (i in 1 until rb.size) { + output?.writeByte(rb[i]) } counter += (rb.size - 1) return counter } } -public fun Input.discardLine(): Int { - return discardUntilDelimiter('\n'.code.toByte()).also { - discard(1) - }.toInt() + 1 -} - -public fun Input.discardWithSeparator( - separator: ByteArray, +/** + * Discard all bytes until [separator] is encountered. Separator is discarded sa well. + * Return the total number of bytes read. + */ +public fun Source.discardWithSeparator( + separator: ByteString, atMost: Int = Int.MAX_VALUE, errorOnEof: Boolean = false, -): Int { - val dummy: Output = object : Output(ChunkBuffer.Pool) { - override fun closeDestination() { - // Do nothing - } +): Int = readWithSeparatorTo(null, separator, atMost, errorOnEof) - override fun flush(source: Memory, offset: Int, length: Int) { - // Do nothing - } +/** + * Discard all symbol until newline is discovered. Carriage return is not discarded. + */ +public fun Source.discardLine( + atMost: Int = Int.MAX_VALUE, + errorOnEof: Boolean = false, +): Int = discardWithSeparator("\n".encodeToByteString(), atMost, errorOnEof) + + +/** + * A [Source] based on [ByteArray] + */ +internal class ByteArraySource( + private val byteArray: ByteArray, + private val offset: Int = 0, + private val size: Int = byteArray.size - offset, +) : RawSource { + + init { + require(offset >= 0) { "Offset must be positive" } + require(offset + size <= byteArray.size) { "End index is ${offset + size}, but the array size is ${byteArray.size}" } } - return readWithSeparatorTo(dummy, separator, atMost, errorOnEof) + private var pointer = offset + + override fun close() { + // Do nothing + } + + override fun readAtMostTo(sink: Buffer, byteCount: Long): Long { + if (pointer == offset + size) return -1 + val byteRead = min(byteCount.toInt(), (size + offset - pointer)) + sink.write(byteArray, pointer, pointer + byteRead) + pointer += byteRead + return byteRead.toLong() + } } + +/** + * A [Source] based on [String] + */ +public class StringSource( + public val string: String, + public val offset: Int = 0, + public val size: Int = string.length - offset, +) : RawSource { + + private var pointer = offset + + override fun close() { + // Do nothing + } + + override fun readAtMostTo(sink: Buffer, byteCount: Long): Long { + if (pointer == offset + size) return -1 + val byteRead = min(byteCount.toInt(), (size + offset - pointer)) + sink.writeString(string, pointer, pointer + byteRead) + pointer += byteRead + return byteRead.toLong() + } +} + +public fun Sink.writeDouble(value: Double) { + writeLong(value.toBits()) +} + +public fun Source.readDouble(): Double = Double.fromBits(readLong()) + +public fun Sink.writeFloat(value: Float) { + writeInt(value.toBits()) +} + +public fun Source.readFloat(): Float = Float.fromBits(readInt()) \ No newline at end of file diff --git a/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/BinaryTest.kt b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/BinaryTest.kt index 530b1a4c..250b8426 100644 --- a/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/BinaryTest.kt +++ b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/BinaryTest.kt @@ -1,6 +1,5 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.core.readInt import kotlin.test.Test import kotlin.test.assertEquals diff --git a/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/EnvelopeFormatTest.kt b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/EnvelopeFormatTest.kt index 999f3175..3200e24b 100644 --- a/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/EnvelopeFormatTest.kt +++ b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/EnvelopeFormatTest.kt @@ -1,6 +1,7 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.core.readBytes +import kotlinx.io.readByteArray +import kotlinx.io.writeString import kotlin.test.Test import kotlin.test.assertEquals @@ -12,7 +13,7 @@ class EnvelopeFormatTest { "d" put 22.2 } data { - writeUtf8String("12345678") + writeString("12345678") } } @@ -22,7 +23,7 @@ class EnvelopeFormatTest { val res = readFromByteArray(byteArray) assertEquals(envelope.meta, res.meta) val bytes = res.data?.read { - readBytes() + readByteArray() } assertEquals("12345678", bytes?.decodeToString()) } @@ -34,13 +35,13 @@ class EnvelopeFormatTest { val res = readFromByteArray(byteArray) assertEquals(envelope.meta, res.meta) val bytes = res.data?.read { - readBytes() + readByteArray() } - assertEquals("12345678", bytes?.decodeToString()) + assertEquals("12345678", bytes?.decodeToString()) } @Test - fun testManualDftl(){ + fun testManualDftl() { val envelopeString = """ #~DFTL #~META @@ -56,8 +57,8 @@ class EnvelopeFormatTest { val res = TaglessEnvelopeFormat.readFromByteArray(envelopeString.encodeToByteArray()) assertEquals(envelope.meta, res.meta) val bytes = res.data?.read { - readBytes() + readByteArray() } - assertEquals("12345678", bytes?.decodeToString()) + assertEquals("12345678", bytes?.decodeToString()) } } \ No newline at end of file diff --git a/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/IOTest.kt b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/IOTest.kt index f02066da..683df330 100644 --- a/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/IOTest.kt +++ b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/IOTest.kt @@ -1,8 +1,9 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.readBytes -import io.ktor.utils.io.core.readUTF8Line +import kotlinx.io.buffered +import kotlinx.io.bytestring.encodeToByteString +import kotlinx.io.readByteArray +import kotlinx.io.readLine import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFails @@ -11,9 +12,9 @@ class IOTest { @Test fun readBytes() { val bytes = ByteArray(8) { it.toByte() } - val input = ByteReadPacket(bytes) - @Suppress("UNUSED_VARIABLE") val first = input.readBytes(4) - val second = input.readBytes(4) + val input = ByteArraySource(bytes).buffered() + @Suppress("UNUSED_VARIABLE") val first = input.readByteArray(4) + val second = input.readByteArray(4) assertEquals(4.toByte(), second[0]) } @@ -31,25 +32,25 @@ class IOTest { binary.read { val array = ByteArray { - val read = readWithSeparatorTo(this, "---".encodeToByteArray()) + discardLine() + val read = readWithSeparatorTo(this, "---".encodeToByteString()) + discardLine() assertEquals(12, read) } assertEquals(""" aaa bbb """.trimIndent(),array.decodeToString().trim()) - assertEquals("ccc", readUTF8Line()?.trim()) + assertEquals("ccc", readLine()?.trim()) } assertFails { binary.read { - discardWithSeparator("---".encodeToByteArray(), atMost = 3 ) + discardWithSeparator("---".encodeToByteString(), atMost = 3 ) } } assertFails { binary.read{ - discardWithSeparator("-+-".encodeToByteArray(), errorOnEof = true) + discardWithSeparator("-+-".encodeToByteString(), errorOnEof = true) } } diff --git a/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/MetaFormatTest.kt b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/MetaFormatTest.kt index 143d202f..52154604 100644 --- a/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/MetaFormatTest.kt +++ b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/MetaFormatTest.kt @@ -7,11 +7,11 @@ import kotlin.test.assertEquals fun Meta.toByteArray(format: MetaFormat = JsonMetaFormat) = ByteArray { - format.writeObject(this@ByteArray, this@toByteArray) + format.writeTo(this@ByteArray, this@toByteArray) } fun MetaFormat.fromByteArray(packet: ByteArray): Meta { - return packet.asBinary().read { readObject(this) } + return packet.asBinary().read { readFrom(this) } } class MetaFormatTest { diff --git a/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/MultipartTest.kt b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/MultipartTest.kt index 2412b969..6ad5d8e3 100644 --- a/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/MultipartTest.kt +++ b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/MultipartTest.kt @@ -1,5 +1,6 @@ package space.kscience.dataforge.io +import kotlinx.io.writeString import space.kscience.dataforge.context.Global import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.int @@ -18,9 +19,9 @@ class MultipartTest { "value" put it } data { - writeUtf8String("Hello World $it") + writeString("Hello World $it") repeat(300) { - writeRawString("$it ") + writeString("$it ") } } } diff --git a/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/ioTestUtils.kt b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/ioTestUtils.kt index 8eeb526b..c07d1cca 100644 --- a/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/ioTestUtils.kt +++ b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/ioTestUtils.kt @@ -1,12 +1,11 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.core.ByteReadPacket -import io.ktor.utils.io.core.use +import kotlinx.io.buffered fun IOFormat.writeToByteArray(obj: T): ByteArray = ByteArray { - writeObject(this, obj) + writeTo(this, obj) } -fun IOFormat.readFromByteArray(array: ByteArray): T = ByteReadPacket(array).use { - readObject(it) +fun IOFormat.readFromByteArray(array: ByteArray): T = ByteArraySource(array).buffered().use { + readFrom(it) } \ No newline at end of file diff --git a/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/fileIO.kt b/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/fileIO.kt index cf88d3ae..c15280f3 100644 --- a/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/fileIO.kt +++ b/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/fileIO.kt @@ -1,8 +1,11 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.core.* -import io.ktor.utils.io.streams.asOutput + import kotlinx.coroutines.runBlocking +import kotlinx.io.Sink +import kotlinx.io.Source +import kotlinx.io.asSink +import kotlinx.io.buffered import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.isEmpty @@ -23,18 +26,18 @@ internal class PathBinary( override val size: Int = Files.size(path).toInt() - fileOffset, ) : Binary { - override fun read(offset: Int, atMost: Int, block: Input.() -> R): R = runBlocking { + override fun read(offset: Int, atMost: Int, block: Source.() -> R): R = runBlocking { readSuspend(offset, atMost, block) } - override suspend fun readSuspend(offset: Int, atMost: Int, block: suspend Input.() -> R): R { + override suspend fun readSuspend(offset: Int, atMost: Int, block: suspend Source.() -> R): R { val actualOffset = offset + fileOffset val actualSize = min(atMost, size - offset) val array = path.inputStream().use { it.skip(actualOffset.toLong()) it.readNBytes(actualSize) } - return ByteReadPacket(array).block() + return ByteArraySource(array).buffered().use { it.block() } } override fun view(offset: Int, binarySize: Int) = PathBinary(path, fileOffset + offset, binarySize) @@ -42,40 +45,40 @@ internal class PathBinary( public fun Path.asBinary(): Binary = PathBinary(this) -public fun Path.read(block: Input.() -> R): R = asBinary().read(block = block) +public fun Path.read(block: Source.() -> R): R = asBinary().read(block = block) /** * Write a live output to a newly created file. If file does not exist, throws error */ -public fun Path.write(block: Output.() -> Unit): Unit { +public fun Path.write(block: Sink.() -> Unit): Unit { val stream = Files.newOutputStream(this, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW) - stream.asOutput().use(block) + stream.asSink().buffered().use(block) } /** * Create a new file or append to exiting one with given output [block] */ -public fun Path.append(block: Output.() -> Unit): Unit { +public fun Path.append(block: Sink.() -> Unit): Unit { val stream = Files.newOutputStream( this, StandardOpenOption.WRITE, StandardOpenOption.APPEND, StandardOpenOption.CREATE ) - stream.asOutput().use(block) + stream.asSink().buffered().use(block) } /** * Create a new file or replace existing one using given output [block] */ -public fun Path.rewrite(block: Output.() -> Unit): Unit { +public fun Path.rewrite(block: Sink.() -> Unit): Unit { val stream = Files.newOutputStream( this, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE ) - stream.asOutput().use(block) + stream.asSink().buffered().use(block) } @DFExperimental -public fun EnvelopeFormat.readFile(path: Path): Envelope = readObject(path.asBinary()) +public fun EnvelopeFormat.readFile(path: Path): Envelope = readFrom(path.asBinary()) /** * Resolve IOFormat based on type @@ -235,7 +238,7 @@ public fun IOPlugin.writeEnvelopeFile( envelopeFormat: EnvelopeFormat = TaggedEnvelopeFormat, ) { path.rewrite { - envelopeFormat.writeObject(this, envelope) + envelopeFormat.writeTo(this, envelope) } } @@ -260,7 +263,7 @@ public fun IOPlugin.writeEnvelopeDirectory( val dataFile = path.resolve(IOPlugin.DATA_FILE_NAME) dataFile.write { envelope.data?.read { - val copied = copyTo(this@write) + val copied = transferTo(this@write) if (copied != envelope.data?.size?.toLong()) { error("The number of copied bytes does not equal data size") } diff --git a/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/resourceIO.kt b/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/resourceIO.kt index f1997d21..2e12c3e1 100644 --- a/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/resourceIO.kt +++ b/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/resourceIO.kt @@ -1,9 +1,11 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.core.Input -import io.ktor.utils.io.streams.asInput +import kotlinx.io.Source +import kotlinx.io.asSource +import kotlinx.io.buffered -public fun IOPlugin.resource(name: String): Binary? = context.javaClass.getResource(name)?.readBytes()?.asBinary() -public inline fun IOPlugin.readResource(name: String, block: Input.() -> R): R = - context.javaClass.getResource(name)?.openStream()?.asInput()?.block() ?: error("Can't read resource $name") \ No newline at end of file +public fun IOPlugin.resource(name: String): Binary? = { }.javaClass.getResource(name)?.readBytes()?.asBinary() + +public inline fun IOPlugin.readResource(name: String, block: Source.() -> R): R = + { }.javaClass.getResource(name)?.openStream()?.asSource()?.buffered()?.block() ?: error("Can't read resource $name") \ No newline at end of file diff --git a/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/workDirectory.kt b/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/workDirectory.kt index efdb43db..94c0e77b 100644 --- a/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/workDirectory.kt +++ b/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/workDirectory.kt @@ -1,7 +1,6 @@ package space.kscience.dataforge.io import space.kscience.dataforge.context.ContextBuilder -import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.set import space.kscience.dataforge.meta.string import java.nio.file.Path diff --git a/dataforge-io/src/jvmTest/kotlin/space/kscience/dataforge/io/FileBinaryTest.kt b/dataforge-io/src/jvmTest/kotlin/space/kscience/dataforge/io/FileBinaryTest.kt index d03c1c1c..c50eee37 100644 --- a/dataforge-io/src/jvmTest/kotlin/space/kscience/dataforge/io/FileBinaryTest.kt +++ b/dataforge-io/src/jvmTest/kotlin/space/kscience/dataforge/io/FileBinaryTest.kt @@ -1,6 +1,5 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.core.writeDouble import space.kscience.dataforge.context.Global import space.kscience.dataforge.misc.DFExperimental import java.nio.file.Files diff --git a/dataforge-io/src/jvmTest/kotlin/space/kscience/dataforge/io/FileEnvelopeTest.kt b/dataforge-io/src/jvmTest/kotlin/space/kscience/dataforge/io/FileEnvelopeTest.kt index ee5ea41f..d9e6d000 100644 --- a/dataforge-io/src/jvmTest/kotlin/space/kscience/dataforge/io/FileEnvelopeTest.kt +++ b/dataforge-io/src/jvmTest/kotlin/space/kscience/dataforge/io/FileEnvelopeTest.kt @@ -1,6 +1,5 @@ package space.kscience.dataforge.io -import io.ktor.utils.io.core.writeDouble import space.kscience.dataforge.context.Global import space.kscience.dataforge.misc.DFExperimental import java.nio.file.Files diff --git a/dataforge-meta/README.md b/dataforge-meta/README.md index 0088dcf7..5f214640 100644 --- a/dataforge-meta/README.md +++ b/dataforge-meta/README.md @@ -6,27 +6,18 @@ Meta definition and basic operations on meta ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-meta:0.6.2-dev-2`. +The Maven coordinates of this project are `space.kscience:dataforge-meta:0.7.0`. -**Gradle Groovy:** -```groovy -repositories { - maven { url 'https://repo.kotlin.link' } - mavenCentral() -} - -dependencies { - implementation 'space.kscience:dataforge-meta:0.6.2-dev-2' -} -``` **Gradle Kotlin DSL:** ```kotlin repositories { maven("https://repo.kotlin.link") + //uncomment to access development builds + //maven("https://maven.pkg.jetbrains.space/spc/p/sci/dev") mavenCentral() } dependencies { - implementation("space.kscience:dataforge-meta:0.6.2-dev-2") + implementation("space.kscience:dataforge-meta:0.7.0") } ``` diff --git a/dataforge-meta/api/dataforge-meta.api b/dataforge-meta/api/dataforge-meta.api index 94878da2..7daa7540 100644 --- a/dataforge-meta/api/dataforge-meta.api +++ b/dataforge-meta/api/dataforge-meta.api @@ -45,9 +45,9 @@ public final class space/kscience/dataforge/meta/False : space/kscience/dataforg public final class space/kscience/dataforge/meta/JsonMetaKt { public static final fun getJSON_ARRAY_KEY (Lspace/kscience/dataforge/meta/Meta$Companion;)Ljava/lang/String; - public static final fun toJson (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lkotlinx/serialization/json/JsonObject; + public static final fun toJson (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lkotlinx/serialization/json/JsonElement; public static final fun toJson (Lspace/kscience/dataforge/meta/Value;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lkotlinx/serialization/json/JsonElement; - public static synthetic fun toJson$default (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lkotlinx/serialization/json/JsonObject; + public static synthetic fun toJson$default (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lkotlinx/serialization/json/JsonElement; public static synthetic fun toJson$default (Lspace/kscience/dataforge/meta/Value;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lkotlinx/serialization/json/JsonElement; public static final fun toMeta (Lkotlinx/serialization/json/JsonElement;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lspace/kscience/dataforge/meta/SealedMeta; public static final fun toMeta (Lkotlinx/serialization/json/JsonObject;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lspace/kscience/dataforge/meta/SealedMeta; @@ -59,11 +59,11 @@ public final class space/kscience/dataforge/meta/JsonMetaKt { public final class space/kscience/dataforge/meta/Laminate : space/kscience/dataforge/meta/TypedMeta { public static final field Companion Lspace/kscience/dataforge/meta/Laminate$Companion; public fun equals (Ljava/lang/Object;)Z + public fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Laminate; + public synthetic fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; + public synthetic fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMeta; public fun getItems ()Ljava/util/Map; public final fun getLayers ()Ljava/util/List; - public fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Laminate; - public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; - public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMeta; public fun getValue ()Lspace/kscience/dataforge/meta/Value; public fun hashCode ()I public final fun merge ()Lspace/kscience/dataforge/meta/SealedMeta; @@ -122,8 +122,8 @@ public abstract interface class space/kscience/dataforge/meta/Meta : space/kscie public static final field TYPE Ljava/lang/String; public static final field VALUE_KEY Ljava/lang/String; public abstract fun equals (Ljava/lang/Object;)Z + public fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; public abstract fun getItems ()Ljava/util/Map; - public fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; public abstract fun getValue ()Lspace/kscience/dataforge/meta/Value; public abstract fun hashCode ()I public fun toMeta ()Lspace/kscience/dataforge/meta/Meta; @@ -137,10 +137,26 @@ public final class space/kscience/dataforge/meta/Meta$Companion { public final fun equals (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/Meta;)Z public final fun getEMPTY ()Lspace/kscience/dataforge/meta/Meta; public final fun hashCode (Lspace/kscience/dataforge/meta/Meta;)I + public final fun serializer ()Lkotlinx/serialization/KSerializer; public final fun toString (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/String; } -public abstract interface annotation class space/kscience/dataforge/meta/MetaBuilder : java/lang/annotation/Annotation { +public final class space/kscience/dataforge/meta/MetaBuilder : space/kscience/dataforge/meta/MutableMeta { + public fun ()V + public fun (Lspace/kscience/dataforge/meta/Value;Ljava/util/Map;)V + public synthetic fun (Lspace/kscience/dataforge/meta/Value;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun equals (Ljava/lang/Object;)Z + public fun getItems ()Ljava/util/Map; + public fun getOrCreate (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaBuilder; + public synthetic fun getOrCreate (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; + public fun getValue ()Lspace/kscience/dataforge/meta/Value; + public fun hashCode ()I + public fun set (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)V + public fun setValue (Lspace/kscience/dataforge/meta/Value;)V + public fun toString ()Ljava/lang/String; +} + +public abstract interface annotation class space/kscience/dataforge/meta/MetaBuilderMarker : java/lang/annotation/Annotation { } public final class space/kscience/dataforge/meta/MetaDelegateKt { @@ -204,11 +220,7 @@ public final class space/kscience/dataforge/meta/MetaKt { public static final fun getIndexed (Lspace/kscience/dataforge/meta/TypedMeta;Lspace/kscience/dataforge/names/Name;)Ljava/util/Map; public static final fun getInt (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Integer; public static final fun getLong (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Long; - public static final synthetic fun getNonNullable (Lspace/kscience/dataforge/meta/Meta;Ljava/lang/String;)Lspace/kscience/dataforge/meta/Meta; - public static final synthetic fun getNonNullable (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; public static final synthetic fun getNonNullable (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/names/NameToken;)Lspace/kscience/dataforge/meta/Meta; - public static final synthetic fun getNonNullable (Lspace/kscience/dataforge/meta/TypedMeta;Ljava/lang/String;)Lspace/kscience/dataforge/meta/TypedMeta; - public static final synthetic fun getNonNullable (Lspace/kscience/dataforge/meta/TypedMeta;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMeta; public static final fun getNumber (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Number; public static final fun getSelf (Lspace/kscience/dataforge/meta/TypedMeta;)Lspace/kscience/dataforge/meta/TypedMeta; public static final fun getShort (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Short; @@ -223,7 +235,7 @@ public final class space/kscience/dataforge/meta/MetaKt { } public abstract interface class space/kscience/dataforge/meta/MetaProvider : space/kscience/dataforge/meta/ValueProvider { - public abstract fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; + public abstract fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; public fun getValue (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Value; } @@ -241,9 +253,10 @@ public final class space/kscience/dataforge/meta/MetaSerializer : kotlinx/serial } public abstract interface class space/kscience/dataforge/meta/MutableMeta : space/kscience/dataforge/meta/Meta, space/kscience/dataforge/meta/MutableMetaProvider { + public static final field Companion Lspace/kscience/dataforge/meta/MutableMeta$Companion; + public synthetic fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; + public fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; public abstract fun getItems ()Ljava/util/Map; - public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; - public fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; public abstract fun getOrCreate (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; public abstract fun getValue ()Lspace/kscience/dataforge/meta/Value; public fun put (Ljava/lang/String;Ljava/lang/Enum;)V @@ -269,6 +282,10 @@ public abstract interface class space/kscience/dataforge/meta/MutableMeta : spac public fun setValue (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Value;)V } +public final class space/kscience/dataforge/meta/MutableMeta$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class space/kscience/dataforge/meta/MutableMetaDelegateKt { public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty; @@ -325,9 +342,9 @@ public final class space/kscience/dataforge/meta/MutableMetaDelegateKt { } public final class space/kscience/dataforge/meta/MutableMetaKt { - public static final fun MutableMeta ()Lspace/kscience/dataforge/meta/ObservableMutableMeta; - public static final fun MutableMeta (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; - public static synthetic fun MutableMeta$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; + public static final fun ObservableMutableMeta ()Lspace/kscience/dataforge/meta/ObservableMutableMeta; + public static final fun ObservableMutableMeta (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; + public static synthetic fun ObservableMutableMeta$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; public static final fun append (Lspace/kscience/dataforge/meta/MutableMeta;Ljava/lang/String;Lspace/kscience/dataforge/meta/Meta;)V public static final fun append (Lspace/kscience/dataforge/meta/MutableMeta;Ljava/lang/String;Lspace/kscience/dataforge/meta/Value;)V public static final fun append (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)V @@ -343,7 +360,6 @@ public final class space/kscience/dataforge/meta/MutableMetaKt { public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Ljava/lang/Iterable;)V public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/meta/Meta;)V public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Ljava/lang/Iterable;)V - public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)V public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/NameToken;Lspace/kscience/dataforge/meta/Meta;)V public static final fun set (Lspace/kscience/dataforge/meta/MutableTypedMeta;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Value;)V public static final fun set (Lspace/kscience/dataforge/meta/MutableValueProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Value;)V @@ -355,8 +371,8 @@ public final class space/kscience/dataforge/meta/MutableMetaKt { } public abstract interface class space/kscience/dataforge/meta/MutableMetaProvider : space/kscience/dataforge/meta/MetaProvider, space/kscience/dataforge/meta/MutableValueProvider { - public abstract fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; - public abstract fun setMeta (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)V + public abstract fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; + public abstract fun set (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)V public abstract fun setValue (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Value;)V } @@ -370,7 +386,7 @@ public final class space/kscience/dataforge/meta/MutableMetaSerializer : kotlinx } public abstract interface class space/kscience/dataforge/meta/MutableTypedMeta : space/kscience/dataforge/meta/MutableMeta, space/kscience/dataforge/meta/TypedMeta { - public abstract fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableTypedMeta; + public abstract fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableTypedMeta; public abstract fun getOrCreate (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableTypedMeta; } @@ -413,11 +429,11 @@ public final class space/kscience/dataforge/meta/ObservableMetaWrapperKt { } public abstract interface class space/kscience/dataforge/meta/ObservableMutableMeta : space/kscience/dataforge/meta/MutableMeta, space/kscience/dataforge/meta/MutableTypedMeta, space/kscience/dataforge/meta/ObservableMeta { - public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; - public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; - public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableTypedMeta; - public fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; - public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMeta; + public synthetic fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; + public synthetic fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; + public synthetic fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableTypedMeta; + public fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; + public synthetic fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMeta; public abstract fun getOrCreate (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; } @@ -429,12 +445,12 @@ public abstract interface class space/kscience/dataforge/meta/ReadOnlySpecificat public class space/kscience/dataforge/meta/Scheme : space/kscience/dataforge/meta/Configurable, space/kscience/dataforge/meta/MetaRepr, space/kscience/dataforge/meta/MutableMetaProvider, space/kscience/dataforge/meta/descriptors/Described { public fun ()V + public synthetic fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; + public fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; public final fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; public synthetic fun getMeta ()Lspace/kscience/dataforge/meta/MutableMeta; public final fun getMeta ()Lspace/kscience/dataforge/meta/ObservableMutableMeta; - public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; - public fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; - public fun setMeta (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)V + public fun set (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)V public fun setValue (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Value;)V public fun toMeta ()Lspace/kscience/dataforge/meta/Laminate; public synthetic fun toMeta ()Lspace/kscience/dataforge/meta/Meta; @@ -463,13 +479,12 @@ public class space/kscience/dataforge/meta/SchemeSpec : space/kscience/dataforge public final class space/kscience/dataforge/meta/SealedMeta : space/kscience/dataforge/meta/TypedMeta { public static final field Companion Lspace/kscience/dataforge/meta/SealedMeta$Companion; - public synthetic fun (ILspace/kscience/dataforge/meta/Value;Ljava/util/Map;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V + public fun (Lspace/kscience/dataforge/meta/Value;Ljava/util/Map;)V public fun equals (Ljava/lang/Object;)Z public fun getItems ()Ljava/util/Map; public fun getValue ()Lspace/kscience/dataforge/meta/Value; public fun hashCode ()I public fun toString ()Ljava/lang/String; - public static final synthetic fun write$Self (Lspace/kscience/dataforge/meta/SealedMeta;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V } public final class space/kscience/dataforge/meta/SealedMeta$$serializer : kotlinx/serialization/internal/GeneratedSerializer { @@ -490,9 +505,13 @@ public final class space/kscience/dataforge/meta/SealedMeta$Companion { public final class space/kscience/dataforge/meta/SealedMetaKt { public static final fun Meta (Ljava/lang/Number;)Lspace/kscience/dataforge/meta/SealedMeta; public static final fun Meta (Ljava/lang/String;)Lspace/kscience/dataforge/meta/SealedMeta; - public static final fun Meta (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/SealedMeta; + public static final fun Meta (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/Meta; public static final fun Meta (Lspace/kscience/dataforge/meta/Value;)Lspace/kscience/dataforge/meta/SealedMeta; public static final fun Meta (Z)Lspace/kscience/dataforge/meta/SealedMeta; + public static final fun MutableMeta ()Lspace/kscience/dataforge/meta/MutableMeta; + public static final fun MutableMeta (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/MutableMeta; + public static synthetic fun MutableMeta$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMeta; + public static final fun SealedMeta (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/SealedMeta; public static final fun seal (Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/SealedMeta; } @@ -541,9 +560,9 @@ public final class space/kscience/dataforge/meta/True : space/kscience/dataforge } public abstract interface class space/kscience/dataforge/meta/TypedMeta : space/kscience/dataforge/meta/Meta { + public synthetic fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; + public fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMeta; public abstract fun getItems ()Ljava/util/Map; - public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; - public fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMeta; public fun toMeta ()Lspace/kscience/dataforge/meta/Meta; } @@ -561,6 +580,8 @@ public abstract interface class space/kscience/dataforge/meta/Value { public final class space/kscience/dataforge/meta/Value$Companion { public static final field TYPE Ljava/lang/String; public final fun of (Ljava/lang/Object;)Lspace/kscience/dataforge/meta/Value; + public final fun parse (Ljava/lang/String;)Lspace/kscience/dataforge/meta/Value; + public final fun serializer ()Lkotlinx/serialization/KSerializer; } public final class space/kscience/dataforge/meta/ValueExtensionsKt { @@ -635,21 +656,11 @@ public final class space/kscience/dataforge/meta/ValueType : java/lang/Enum { public static final field NULL Lspace/kscience/dataforge/meta/ValueType; public static final field NUMBER Lspace/kscience/dataforge/meta/ValueType; public static final field STRING Lspace/kscience/dataforge/meta/ValueType; + public static fun getEntries ()Lkotlin/enums/EnumEntries; public static fun valueOf (Ljava/lang/String;)Lspace/kscience/dataforge/meta/ValueType; public static fun values ()[Lspace/kscience/dataforge/meta/ValueType; } -public final class space/kscience/dataforge/meta/ValueType$$serializer : kotlinx/serialization/internal/GeneratedSerializer { - public static final field INSTANCE Lspace/kscience/dataforge/meta/ValueType$$serializer; - public fun childSerializers ()[Lkotlinx/serialization/KSerializer; - public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; - public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lspace/kscience/dataforge/meta/ValueType; - public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; - public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V - public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lspace/kscience/dataforge/meta/ValueType;)V - public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; -} - public final class space/kscience/dataforge/meta/ValueType$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } @@ -661,34 +672,30 @@ public abstract interface class space/kscience/dataforge/meta/descriptors/Descri public final class space/kscience/dataforge/meta/descriptors/MetaDescriptor { public static final field Companion Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor$Companion; public fun ()V - public synthetic fun (ILjava/lang/String;Ljava/util/Map;ZLspace/kscience/dataforge/meta/descriptors/ValueRequirement;Ljava/util/List;Ljava/lang/String;Lspace/kscience/dataforge/meta/Value;ZLspace/kscience/dataforge/meta/Meta;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V - public fun (Ljava/lang/String;Ljava/util/Map;ZLspace/kscience/dataforge/meta/descriptors/ValueRequirement;Ljava/util/List;Ljava/lang/String;Lspace/kscience/dataforge/meta/Value;ZLspace/kscience/dataforge/meta/Meta;)V - public synthetic fun (Ljava/lang/String;Ljava/util/Map;ZLspace/kscience/dataforge/meta/descriptors/ValueRequirement;Ljava/util/List;Ljava/lang/String;Lspace/kscience/dataforge/meta/Value;ZLspace/kscience/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Ljava/util/Map;ZLspace/kscience/dataforge/meta/descriptors/ValueRestriction;Ljava/util/List;Ljava/lang/String;Lspace/kscience/dataforge/meta/Value;Lspace/kscience/dataforge/meta/Meta;)V + public synthetic fun (Ljava/lang/String;Ljava/util/Map;ZLspace/kscience/dataforge/meta/descriptors/ValueRestriction;Ljava/util/List;Ljava/lang/String;Lspace/kscience/dataforge/meta/Value;Lspace/kscience/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ljava/lang/String; public final fun component2 ()Ljava/util/Map; public final fun component3 ()Z - public final fun component4 ()Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; + public final fun component4 ()Lspace/kscience/dataforge/meta/descriptors/ValueRestriction; public final fun component5 ()Ljava/util/List; public final fun component6 ()Ljava/lang/String; public final fun component7 ()Lspace/kscience/dataforge/meta/Value; - public final fun component8 ()Z - public final fun component9 ()Lspace/kscience/dataforge/meta/Meta; - public final fun copy (Ljava/lang/String;Ljava/util/Map;ZLspace/kscience/dataforge/meta/descriptors/ValueRequirement;Ljava/util/List;Ljava/lang/String;Lspace/kscience/dataforge/meta/Value;ZLspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; - public static synthetic fun copy$default (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Ljava/lang/String;Ljava/util/Map;ZLspace/kscience/dataforge/meta/descriptors/ValueRequirement;Ljava/util/List;Ljava/lang/String;Lspace/kscience/dataforge/meta/Value;ZLspace/kscience/dataforge/meta/Meta;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; + public final fun component8 ()Lspace/kscience/dataforge/meta/Meta; + public final fun copy (Ljava/lang/String;Ljava/util/Map;ZLspace/kscience/dataforge/meta/descriptors/ValueRestriction;Ljava/util/List;Ljava/lang/String;Lspace/kscience/dataforge/meta/Value;Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; + public static synthetic fun copy$default (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Ljava/lang/String;Ljava/util/Map;ZLspace/kscience/dataforge/meta/descriptors/ValueRestriction;Ljava/util/List;Ljava/lang/String;Lspace/kscience/dataforge/meta/Value;Lspace/kscience/dataforge/meta/Meta;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; public fun equals (Ljava/lang/Object;)Z public final fun getAttributes ()Lspace/kscience/dataforge/meta/Meta; public final fun getChildren ()Ljava/util/Map; public final fun getDefaultNode ()Lspace/kscience/dataforge/meta/Meta; public final fun getDefaultValue ()Lspace/kscience/dataforge/meta/Value; + public final fun getDescription ()Ljava/lang/String; public final fun getIndexKey ()Ljava/lang/String; - public final fun getInfo ()Ljava/lang/String; public final fun getMultiple ()Z - public final fun getReadOnly ()Z - public final fun getValueRequirement ()Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; + public final fun getValueRestriction ()Lspace/kscience/dataforge/meta/descriptors/ValueRestriction; public final fun getValueTypes ()Ljava/util/List; public fun hashCode ()I public fun toString ()Ljava/lang/String; - public static final synthetic fun write$Self (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V } public final class space/kscience/dataforge/meta/descriptors/MetaDescriptor$$serializer : kotlinx/serialization/internal/GeneratedSerializer { @@ -703,6 +710,7 @@ public final class space/kscience/dataforge/meta/descriptors/MetaDescriptor$$ser } public final class space/kscience/dataforge/meta/descriptors/MetaDescriptor$Companion { + public final fun getEMPTY ()Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; public final fun serializer ()Lkotlinx/serialization/KSerializer; } @@ -719,9 +727,8 @@ public final class space/kscience/dataforge/meta/descriptors/MetaDescriptorBuild public final fun getIndexKey ()Ljava/lang/String; public final fun getInfo ()Ljava/lang/String; public final fun getMultiple ()Z - public final fun getReadOnly ()Z - public final fun getType ()Ljava/util/List; - public final fun getValueRequirement ()Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; + public final fun getValueRestriction ()Lspace/kscience/dataforge/meta/descriptors/ValueRestriction; + public final fun getValueTypes ()Ljava/util/List; public final fun item (Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder; public static synthetic fun item$default (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder; public final fun node (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder; @@ -733,10 +740,9 @@ public final class space/kscience/dataforge/meta/descriptors/MetaDescriptorBuild public final fun setIndexKey (Ljava/lang/String;)V public final fun setInfo (Ljava/lang/String;)V public final fun setMultiple (Z)V - public final fun setReadOnly (Z)V - public final fun setType (Ljava/util/List;)V - public final fun setValueRequirement (Lspace/kscience/dataforge/meta/descriptors/ValueRequirement;)V - public final fun type (Lspace/kscience/dataforge/meta/ValueType;[Lspace/kscience/dataforge/meta/ValueType;)V + public final fun setValueRestriction (Lspace/kscience/dataforge/meta/descriptors/ValueRestriction;)V + public final fun setValueTypes (Ljava/util/List;)V + public final fun valueType (Lspace/kscience/dataforge/meta/ValueType;[Lspace/kscience/dataforge/meta/ValueType;)V } public final class space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilderKt { @@ -764,12 +770,13 @@ public final class space/kscience/dataforge/meta/descriptors/MetaDescriptorKt { public static final fun validate (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lspace/kscience/dataforge/meta/Value;)Z } -public final class space/kscience/dataforge/meta/descriptors/ValueRequirement : java/lang/Enum { - public static final field ABSENT Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; - public static final field NONE Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; - public static final field REQUIRED Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; - public static fun valueOf (Ljava/lang/String;)Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; - public static fun values ()[Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; +public final class space/kscience/dataforge/meta/descriptors/ValueRestriction : java/lang/Enum { + public static final field ABSENT Lspace/kscience/dataforge/meta/descriptors/ValueRestriction; + public static final field NONE Lspace/kscience/dataforge/meta/descriptors/ValueRestriction; + public static final field REQUIRED Lspace/kscience/dataforge/meta/descriptors/ValueRestriction; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/dataforge/meta/descriptors/ValueRestriction; + public static fun values ()[Lspace/kscience/dataforge/meta/descriptors/ValueRestriction; } public final class space/kscience/dataforge/meta/transformations/KeepTransformationRule : space/kscience/dataforge/meta/transformations/TransformationRule { @@ -788,7 +795,10 @@ public final class space/kscience/dataforge/meta/transformations/KeepTransformat public abstract interface class space/kscience/dataforge/meta/transformations/MetaConverter { public static final field Companion Lspace/kscience/dataforge/meta/transformations/MetaConverter$Companion; - public abstract fun metaToObject (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Object; + public fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; + public abstract fun getType ()Lkotlin/reflect/KType; + public fun metaToObject (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Object; + public abstract fun metaToObjectOrNull (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Object; public abstract fun objectToMeta (Ljava/lang/Object;)Lspace/kscience/dataforge/meta/Meta; } @@ -893,6 +903,10 @@ public abstract interface annotation class space/kscience/dataforge/misc/DFExper public abstract interface annotation class space/kscience/dataforge/misc/DFInternal : java/lang/annotation/Annotation { } +public abstract interface annotation class space/kscience/dataforge/misc/DfId : java/lang/annotation/Annotation { + public abstract fun id ()Ljava/lang/String; +} + public abstract interface class space/kscience/dataforge/misc/Named { public static final field Companion Lspace/kscience/dataforge/misc/Named$Companion; public abstract fun getName ()Lspace/kscience/dataforge/names/Name; @@ -906,10 +920,6 @@ public final class space/kscience/dataforge/misc/NamedKt { public static final fun isAnonymous (Lspace/kscience/dataforge/misc/Named;)Z } -public abstract interface annotation class space/kscience/dataforge/misc/Type : java/lang/annotation/Annotation { - public abstract fun id ()Ljava/lang/String; -} - public final class space/kscience/dataforge/names/Name { public static final field Companion Lspace/kscience/dataforge/names/Name$Companion; public static final field NAME_SEPARATOR Ljava/lang/String; @@ -944,6 +954,7 @@ public final class space/kscience/dataforge/names/NameKt { public static synthetic fun get$default (Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/Object; public static final fun getLength (Lspace/kscience/dataforge/names/Name;)I public static final fun isEmpty (Lspace/kscience/dataforge/names/Name;)Z + public static final fun last (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/names/NameToken; public static final fun lastOrNull (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/names/NameToken; public static final fun parseAsName (Ljava/lang/String;Z)Lspace/kscience/dataforge/names/Name; public static synthetic fun parseAsName$default (Ljava/lang/String;ZILjava/lang/Object;)Lspace/kscience/dataforge/names/Name; diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/JsonMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/JsonMeta.kt index 7dc44785..36373582 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/JsonMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/JsonMeta.kt @@ -81,7 +81,7 @@ public fun JsonPrimitive.toValue(descriptor: MetaDescriptor?): Value = when (thi content.asValue() } else { //consider using LazyParse - content.parseValue() + Value.parse(content) } } } diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Laminate.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Laminate.kt index 966e7750..87284107 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Laminate.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Laminate.kt @@ -17,8 +17,8 @@ public class Laminate internal constructor(public val layers: List) : Type } } - override fun getMeta(name: Name): Laminate? { - val childLayers = layers.mapNotNull { it.getMeta(name) } + override fun get(name: Name): Laminate? { + val childLayers = layers.mapNotNull { it.get(name) } return if (childLayers.isEmpty()) null else Laminate(childLayers) } diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt index 589f02d7..420625ca 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt @@ -2,7 +2,7 @@ package space.kscience.dataforge.meta import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json -import space.kscience.dataforge.misc.Type +import space.kscience.dataforge.misc.DfId import space.kscience.dataforge.misc.unsafeCast import space.kscience.dataforge.names.* import kotlin.jvm.JvmName @@ -21,9 +21,9 @@ public interface MetaRepr { * A container for meta nodes */ public fun interface MetaProvider : ValueProvider { - public fun getMeta(name: Name): Meta? + public operator fun get(name: Name): Meta? - override fun getValue(name: Name): Value? = getMeta(name)?.value + override fun getValue(name: Name): Value? = get(name)?.value } /** @@ -31,13 +31,13 @@ public fun interface MetaProvider : ValueProvider { * TODO add documentation * Same name siblings are supported via elements with the same [Name] but different indices. */ -@Type(Meta.TYPE) +@DfId(Meta.TYPE) @Serializable(MetaSerializer::class) public interface Meta : MetaRepr, MetaProvider { public val value: Value? public val items: Map - override fun getMeta(name: Name): Meta? { + override fun get(name: Name): Meta? { tailrec fun Meta.find(name: Name): Meta? = if (name.isEmpty()) { this } else { @@ -50,7 +50,9 @@ public interface Meta : MetaRepr, MetaProvider { override fun toMeta(): Meta = this override fun toString(): String + override fun equals(other: Any?): Boolean + override fun hashCode(): Int public companion object { @@ -106,21 +108,13 @@ public operator fun Meta.get(token: NameToken): Meta? = items[token] * * If [name] is empty return current [Meta] */ -public operator fun Meta?.get(name: Name): Meta? = this?.getMeta(name) - -@Deprecated("Use nullable receiver", level = DeprecationLevel.HIDDEN) -@JvmName("getNonNullable") -public operator fun Meta.get(name: Name): Meta? = getMeta(name) +public operator fun Meta?.get(name: Name): Meta? = this?.get(name) /** * Parse [Name] from [key] using full name notation and pass it to [Meta.get] */ public operator fun Meta?.get(key: String): Meta? = this?.get(key.parseAsName(true)) -@Deprecated("Use nullable receiver", level = DeprecationLevel.HIDDEN) -@JvmName("getNonNullable") -public operator fun Meta.get(key: String): Meta? = get(key.parseAsName(true)) - /** * Get all items matching given name. The index of the last element, if present is used as a [Regex], * against which indexes of elements are matched. @@ -157,7 +151,7 @@ public interface TypedMeta> : Meta { override val items: Map - override fun getMeta(name: Name): M? { + override fun get(name: Name): M? { tailrec fun M.find(name: Name): M? = if (name.isEmpty()) { this } else { @@ -180,28 +174,17 @@ public inline val > TypedMeta.self: M get() = unsafeCast() public operator fun > TypedMeta?.get(token: NameToken): M? = this?.items?.get(token) /** - * Perform recursive item search using given [name]. Each [NameToken] is treated as a name in [TypedMeta.items] of a parent node. + * Retrieves a meta node with the given name from the nullable [TypedMeta] object. * - * If [name] is empty return current [Meta] + * @param name The name of the meta node to retrieve. + * @return The meta node with the given name, or null if it doesn't exist. */ -public tailrec operator fun > TypedMeta?.get(name: Name): M? = when { - this == null -> null - name.isEmpty() -> self - else -> get(name.firstOrNull()!!)?.get(name.cutFirst()) -} - -@Deprecated("Use nullable receiver", level = DeprecationLevel.HIDDEN) -@JvmName("getNonNullable") -public operator fun > TypedMeta.get(name: Name): M? = get(name) +public operator fun > M?.get(name: Name): M? = this?.get(name) /** * Parse [Name] from [key] using full name notation and pass it to [TypedMeta.get] */ -public operator fun > TypedMeta?.get(key: String): M? = this[key.parseAsName(true)] - -@Deprecated("Use nullable receiver", level = DeprecationLevel.HIDDEN) -@JvmName("getNonNullable") -public operator fun > TypedMeta.get(key: String): M? = get(key) +public operator fun > M?.get(key: String): M? = this?.get(key.parseAsName(true)) /** diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt index 94b11c93..73923d56 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt @@ -8,28 +8,28 @@ import kotlin.properties.ReadOnlyProperty /* Meta delegates */ public fun MetaProvider.node(key: Name? = null): ReadOnlyProperty = ReadOnlyProperty { _, property -> - getMeta(key ?: property.name.asName()) + get(key ?: property.name.asName()) } public fun MetaProvider.node( key: Name? = null, converter: MetaConverter ): ReadOnlyProperty = ReadOnlyProperty { _, property -> - getMeta(key ?: property.name.asName())?.let { converter.metaToObject(it) } + get(key ?: property.name.asName())?.let { converter.metaToObject(it) } } /** * A property delegate that uses custom key */ public fun MetaProvider.value(key: Name? = null): ReadOnlyProperty = ReadOnlyProperty { _, property -> - getMeta(key ?: property.name.asName())?.value + get(key ?: property.name.asName())?.value } public fun MetaProvider.value( key: Name? = null, reader: (Value?) -> R ): ReadOnlyProperty = ReadOnlyProperty { _, property -> - reader(getMeta(key ?: property.name.asName())?.value) + reader(get(key ?: property.name.asName())?.value) } //TODO add caching for sealed nodes diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt index b8e565f7..7e05d215 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt @@ -11,14 +11,14 @@ import kotlin.js.JsName * Mark a meta builder */ @DslMarker -public annotation class MetaBuilder +public annotation class MetaBuilderMarker /** * A generic interface that gives access to getting and setting meta notes and values */ public interface MutableMetaProvider : MetaProvider, MutableValueProvider { - override fun getMeta(name: Name): MutableMeta? - public fun setMeta(name: Name, node: Meta?) + override fun get(name: Name): MutableMeta? + public operator fun set(name: Name, node: Meta?) override fun setValue(name: Name, value: Value?) } @@ -27,7 +27,7 @@ public interface MutableMetaProvider : MetaProvider, MutableValueProvider { * TODO documentation */ @Serializable(MutableMetaSerializer::class) -@MetaBuilder +@MetaBuilderMarker public interface MutableMeta : Meta, MutableMetaProvider { override val items: Map @@ -37,7 +37,7 @@ public interface MutableMeta : Meta, MutableMetaProvider { */ override var value: Value? - override fun getMeta(name: Name): MutableMeta? { + override fun get(name: Name): MutableMeta? { tailrec fun MutableMeta.find(name: Name): MutableMeta? = if (name.isEmpty()) { this } else { @@ -83,19 +83,19 @@ public interface MutableMeta : Meta, MutableMetaProvider { } public infix fun Name.put(meta: Meta) { - setMeta(this, meta) + set(this, meta) } public infix fun Name.put(repr: MetaRepr) { - setMeta(this, repr.toMeta()) + set(this, repr.toMeta()) } - public infix fun Name.put(mutableMeta: MutableMeta.() -> Unit) { - setMeta(this, Meta(mutableMeta)) + public infix fun Name.put(builder: MutableMeta.() -> Unit) { + getOrCreate(this).apply(builder) } public infix fun String.put(meta: Meta) { - setMeta(Name.parse(this), meta) + set(Name.parse(this), meta) } public infix fun String.put(value: Value?) { @@ -123,7 +123,7 @@ public interface MutableMeta : Meta, MutableMetaProvider { } public infix fun String.put(repr: MetaRepr) { - setMeta(Name.parse(this), repr.toMeta()) + set(Name.parse(this), repr.toMeta()) } public infix fun String.putIndexed(iterable: Iterable) { @@ -131,15 +131,10 @@ public interface MutableMeta : Meta, MutableMetaProvider { } public infix fun String.put(builder: MutableMeta.() -> Unit) { - setMeta(Name.parse(this), MutableMeta(builder)) + getOrCreate(parseAsName()).apply(builder) } } -/** - * Set or replace node at given [name] - */ -public operator fun MutableMetaProvider.set(name: Name, meta: Meta): Unit = setMeta(name, meta) - /** * Set or replace value at given [name] */ @@ -154,24 +149,24 @@ public interface MutableTypedMeta> : TypedMeta, Mutab */ @DFExperimental public fun attach(name: Name, node: M) - override fun getMeta(name: Name): M? + override fun get(name: Name): M? override fun getOrCreate(name: Name): M } public fun > M.getOrCreate(key: String): M = getOrCreate(Name.parse(key)) public fun MutableMetaProvider.remove(name: Name) { - setMeta(name, null) + set(name, null) } public fun MutableMetaProvider.remove(key: String) { - setMeta(Name.parse(key), null) + set(Name.parse(key), null) } // node setters -public operator fun MutableMetaProvider.set(Key: NameToken, value: Meta): Unit = setMeta(Key.asName(), value) -public operator fun MutableMetaProvider.set(key: String, value: Meta): Unit = setMeta(Name.parse(key), value) +public operator fun MutableMetaProvider.set(Key: NameToken, value: Meta): Unit = set(Key.asName(), value) +public operator fun MutableMetaProvider.set(key: String, value: Meta): Unit = set(Name.parse(key), value) //public fun MutableMeta.set(key: String, index: String, value: Value?): Unit = @@ -319,7 +314,7 @@ private class MutableMetaImpl( ) @ThreadSafe - override fun setMeta(name: Name, node: Meta?) { + override fun set(name: Name, node: Meta?) { val oldItem: ObservableMutableMeta? = get(name) if (oldItem != node) { when (name.length) { @@ -346,7 +341,7 @@ private class MutableMetaImpl( newNode.adoptBy(this, token) children[token] = newNode } - items[token]?.setMeta(name.cutFirst(), node) + items[token]?.set(name.cutFirst(), node) } } invalidate(name) @@ -381,16 +376,14 @@ public fun Meta.toMutableMeta(): ObservableMutableMeta = MutableMetaImpl(value, public fun Meta.asMutableMeta(): MutableMeta = (this as? MutableMeta) ?: toMutableMeta() -@Suppress("FunctionName") -@JsName("newMutableMeta") -public fun MutableMeta(): ObservableMutableMeta = MutableMetaImpl(null) +@JsName("newObservableMutableMeta") +public fun ObservableMutableMeta(): ObservableMutableMeta = MutableMetaImpl(null) /** * Build a [MutableMeta] using given transformation */ -@Suppress("FunctionName") -public inline fun MutableMeta(builder: MutableMeta.() -> Unit = {}): ObservableMutableMeta = - MutableMeta().apply(builder) +public inline fun ObservableMutableMeta(builder: MutableMeta.() -> Unit = {}): ObservableMutableMeta = + ObservableMutableMeta().apply(builder) /** @@ -407,7 +400,7 @@ private class MutableMetaWithDefault( override val items: Map get() { val sourceKeys: Collection = source[rootName]?.items?.keys ?: emptyList() - val defaultKeys: Collection = default.getMeta(rootName)?.items?.keys ?: emptyList() + val defaultKeys: Collection = default[rootName]?.items?.keys ?: emptyList() //merging keys for primary and default node return (sourceKeys + defaultKeys).associateWith { MutableMetaWithDefault(source, default, rootName + it) @@ -415,12 +408,12 @@ private class MutableMetaWithDefault( } override var value: Value? - get() = source[rootName]?.value ?: default.getMeta(rootName)?.value + get() = source[rootName]?.value ?: default.get(rootName)?.value set(value) { source[rootName] = value } - override fun getMeta(name: Name): MutableMeta = MutableMetaWithDefault(source, default, rootName + name) + override fun get(name: Name): MutableMeta = MutableMetaWithDefault(source, default, rootName + name) override fun toString(): String = Meta.toString(this) override fun equals(other: Any?): Boolean = Meta.equals(this, other as? Meta) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt index 32d1017a..0f28523c 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt @@ -11,31 +11,31 @@ import kotlin.reflect.KProperty public fun MutableMetaProvider.node(key: Name? = null): ReadWriteProperty = object : ReadWriteProperty { override fun getValue(thisRef: Any?, property: KProperty<*>): Meta? { - return getMeta(key ?: property.name.asName()) + return get(key ?: property.name.asName()) } override fun setValue(thisRef: Any?, property: KProperty<*>, value: Meta?) { val name = key ?: property.name.asName() - setMeta(name, value) + set(name, value) } } public fun MutableMetaProvider.node(key: Name? = null, converter: MetaConverter): ReadWriteProperty = object : ReadWriteProperty { override fun getValue(thisRef: Any?, property: KProperty<*>): T? { - return getMeta(key ?: property.name.asName())?.let { converter.metaToObject(it) } + return get(key ?: property.name.asName())?.let { converter.metaToObject(it) } } override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) { val name = key ?: property.name.asName() - setMeta(name, value?.let { converter.objectToMeta(it) }) + set(name, value?.let { converter.objectToMeta(it) }) } } public fun MutableMetaProvider.value(key: Name? = null): ReadWriteProperty = object : ReadWriteProperty { override fun getValue(thisRef: Any?, property: KProperty<*>): Value? = - getMeta(key ?: property.name.asName())?.value + get(key ?: property.name.asName())?.value override fun setValue(thisRef: Any?, property: KProperty<*>, value: Value?) { setValue(key ?: property.name.asName(), value) @@ -48,7 +48,7 @@ public fun MutableMetaProvider.value( reader: (Value?) -> T ): ReadWriteProperty = object : ReadWriteProperty { override fun getValue(thisRef: Any?, property: KProperty<*>): T = - reader(getMeta(key ?: property.name.asName())?.value) + reader(get(key ?: property.name.asName())?.value) override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { setValue(key ?: property.name.asName(), writer(value)) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMeta.kt index 835c7e9a..5a2b05f7 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMeta.kt @@ -36,7 +36,7 @@ public interface ObservableMeta : Meta { public interface ObservableMutableMeta : ObservableMeta, MutableMeta, MutableTypedMeta { override fun getOrCreate(name: Name): ObservableMutableMeta - override fun getMeta(name: Name): ObservableMutableMeta? { + override fun get(name: Name): ObservableMutableMeta? { tailrec fun ObservableMutableMeta.find(name: Name): ObservableMutableMeta? = if (name.isEmpty()) { this } else { diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMetaWrapper.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMetaWrapper.kt index d244e8d3..76645d83 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMetaWrapper.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMetaWrapper.kt @@ -17,8 +17,8 @@ private class ObservableMetaWrapper( ObservableMetaWrapper(root, absoluteName + it, listeners) } - override fun getMeta(name: Name): ObservableMutableMeta? = - root.getMeta(name)?.let { ObservableMetaWrapper(root, this.absoluteName + name, listeners) } + override fun get(name: Name): ObservableMutableMeta? = + root.get(name)?.let { ObservableMetaWrapper(root, this.absoluteName + name, listeners) } @ThreadSafe override fun onChange(owner: Any?, callback: Meta.(name: Name) -> Unit) { @@ -49,9 +49,11 @@ private class ObservableMetaWrapper( override fun getOrCreate(name: Name): ObservableMutableMeta = ObservableMetaWrapper(root, this.absoluteName + name, listeners) - override fun setMeta(name: Name, node: Meta?) { + override fun set(name: Name, node: Meta?) { val oldMeta = get(name) - root.setMeta(absoluteName + name, node) + //don't forget to remove listener + oldMeta?.removeListener(this) + root.set(absoluteName + name, node) if (oldMeta != node) { invalidate(name) } @@ -67,7 +69,7 @@ private class ObservableMetaWrapper( override fun attach(name: Name, node: ObservableMutableMeta) { set(name, node) node.onChange(this) { changeName -> - setMeta(name + changeName, this[changeName]) + set(name + changeName, this[changeName]) } } } diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt index 653c8b05..90473286 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt @@ -47,11 +47,11 @@ public open class Scheme : Described, MetaRepr, MutableMetaProvider, Configurabl return descriptor?.validate(meta) ?: true } - override fun getMeta(name: Name): MutableMeta? = meta.getMeta(name) + override fun get(name: Name): MutableMeta? = meta.get(name) - override fun setMeta(name: Name, node: Meta?) { + override fun set(name: Name, node: Meta?) { if (validate(name, meta)) { - meta.setMeta(name, node) + meta.set(name, node) } else { error("Validation failed for node $node at $name") } @@ -110,8 +110,8 @@ public open class Scheme : Described, MetaRepr, MutableMetaProvider, Configurabl override fun equals(other: Any?): Boolean = Meta.equals(this, other as? Meta) override fun hashCode(): Int = Meta.hashCode(this) - override fun setMeta(name: Name, node: Meta?) { - targetMeta.setMeta(name, node) + override fun set(name: Name, node: Meta?) { + targetMeta.set(name, node) invalidate(name) } @@ -120,9 +120,9 @@ public open class Scheme : Described, MetaRepr, MutableMetaProvider, Configurabl @DFExperimental override fun attach(name: Name, node: ObservableMutableMeta) { //TODO implement zero-copy attachment - setMeta(name, node) + set(name, node) node.onChange(this) { changeName -> - setMeta(name + changeName, this[changeName]) + set(name + changeName, this[changeName]) } } diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt index 6c8ab3e9..217a6a04 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt @@ -1,16 +1,17 @@ package space.kscience.dataforge.meta import kotlinx.serialization.Serializable -import space.kscience.dataforge.names.NameToken +import space.kscience.dataforge.names.* +import kotlin.js.JsName /** * The meta implementation which is guaranteed to be immutable. * */ @Serializable -public class SealedMeta internal constructor( +public class SealedMeta( override val value: Value?, - override val items: Map + override val items: Map, ) : TypedMeta { override fun toString(): String = Meta.toString(this) override fun equals(other: Any?): Boolean = Meta.equals(this, other as? Meta) @@ -26,7 +27,7 @@ public class SealedMeta internal constructor( } /** - * 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. */ public fun Meta.seal(): SealedMeta = this as? SealedMeta ?: SealedMeta( value, @@ -47,7 +48,79 @@ public fun Meta(value: String): SealedMeta = Meta(value.asValue()) @Suppress("FunctionName") public fun Meta(value: Boolean): SealedMeta = Meta(value.asValue()) -@Suppress("FunctionName") -public inline fun Meta(builder: MutableMeta.() -> Unit): SealedMeta = - MutableMeta(builder).seal() +/** + * A lightweight mutable meta without an observability + */ +@PublishedApi +internal class MetaBuilder( + override var value: Value? = null, + override val items: MutableMap = hashMapOf(), +) : MutableMeta { + + override fun getOrCreate(name: Name): MetaBuilder { + val existing = get(name) as? MetaBuilder + return if (existing == null) { + val newItem = MetaBuilder() + set(name, newItem) + newItem + } else { + existing + } + } + + private fun wrap(meta: Meta): MetaBuilder = meta as? MetaBuilder ?: MetaBuilder( + meta.value, + meta.items.mapValuesTo(hashMapOf()) { wrap(it.value) } + ) + + + override fun set(name: Name, node: Meta?) { + when (name.length) { + 0 -> error("Can't set a meta with empty name") + 1 -> { + val token = name.first() + //remove child and invalidate if argument is null + if (node == null) { + items.remove(token) + } else { + items[token] = wrap(node) + } + } + + else -> { + getOrCreate(name.first().asName()).set(name.cutFirst(), node) + } + } + } + + override fun toString(): String = Meta.toString(this) + + override fun equals(other: Any?): Boolean = Meta.equals(this, other as? Meta) + + override fun hashCode(): Int = Meta.hashCode(this) +} + +/** + * Create a read-only meta. + */ +public inline fun Meta(builder: MutableMeta.() -> Unit): Meta = + MetaBuilder().apply(builder).seal() + +/** + * Create an immutable meta. + */ +public inline fun SealedMeta(builder: MutableMeta.() -> Unit): SealedMeta = + MetaBuilder().apply(builder).seal() + +/** + * Create an empty meta mutable meta. + */ +@JsName("newMutableMeta") +public fun MutableMeta(): MutableMeta = MetaBuilder() + +/** + * Create a mutable meta with given builder. + */ +public inline fun MutableMeta(builder: MutableMeta.() -> Unit = {}): MutableMeta = + MutableMeta().apply(builder) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Value.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Value.kt index 73950f53..66e14c86 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Value.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Value.kt @@ -64,6 +64,7 @@ public interface Value { ListValue(list) } } + is DoubleArray -> value.asValue() is IntArray -> value.asValue() is FloatArray -> value.asValue() @@ -76,6 +77,41 @@ public interface Value { else -> throw IllegalArgumentException("Unrecognized type of the object (${value::class}) converted to Value") } } + + /** + * Parse value from string. Double-quoted strings are parsed literally. true/false are parsed as booleans + */ + public fun parse(string: String): Value { + + //Trying to get integer + if (string.isEmpty() || string == Null.string) { + return Null + } + + //string constants + if (string.startsWith("\"") && string.endsWith("\"")) { + return StringValue(string.substring(1, string.length - 2)) + } + + string.toIntOrNull()?.let { + return NumberValue(it) + } + + string.toDoubleOrNull()?.let { + return NumberValue(it) + } + + if ("true" == string) { + return True + } + + if ("false" == string) { + return False + } + + //Give up and return a StringValue + return StringValue(string) + } } } @@ -140,7 +176,7 @@ public class NumberValue(public val number: Number) : Value { val otherNumber = other.numberOrNull ?: return false - if(number == otherNumber) return true + if (number == otherNumber) return true //Do not change the order of comparison. On JS number is the instance of all types return when (numberOrNull) { @@ -228,34 +264,5 @@ public fun > E.asValue(): Value = EnumValue(this) /** * Create Value from String using the closest match conversion */ -public fun String.parseValue(): Value { - - //Trying to get integer - if (isEmpty() || this == Null.string) { - return Null - } - - //string constants - if (startsWith("\"") && endsWith("\"")) { - return StringValue(substring(1, length - 2)) - } - - toIntOrNull()?.let { - return NumberValue(it) - } - - toDoubleOrNull()?.let { - return NumberValue(it) - } - - if ("true" == this) { - return True - } - - if ("false" == this) { - return False - } - - //Give up and return a StringValue - return StringValue(this) -} \ No newline at end of file +@Deprecated("Use Value.parse(this) instead", ReplaceWith("Value.parse(this)")) +public fun String.parseValue(): Value = Value.parse(this) \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptor.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptor.kt index b6a91631..742b89ed 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptor.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptor.kt @@ -7,7 +7,7 @@ import space.kscience.dataforge.names.* /** * Restrictions on value in the node */ -public enum class ValueRequirement { +public enum class ValueRestriction { /** * No restrictions */ @@ -26,26 +26,25 @@ public enum class ValueRequirement { /** * The descriptor for a meta - * @param info description text + * @param description description text * @param children child descriptors for this node * @param multiple True if same name siblings with this name are allowed - * @param valueRequirement The requirements for node content + * @param valueRestriction The requirements for node content * @param valueTypes list of allowed types for [Meta.value], null if all values are allowed. * Empty list means that no value should be present in this node. * @param indexKey An index field by which this node is identified in case of same name siblings construct * @param defaultValue the default [Meta.value] for the node - * @param attributes additional attributes of this descriptor. For example validation and widget parameters + * @param attributes additional attributes of this descriptor. For example, validation and widget parameters */ @Serializable public data class MetaDescriptor( - public val info: String? = null, + public val description: String? = null, public val children: Map = emptyMap(), public val multiple: Boolean = false, - public val valueRequirement: ValueRequirement = ValueRequirement.NONE, + public val valueRestriction: ValueRestriction = ValueRestriction.NONE, public val valueTypes: List? = null, public val indexKey: String = Meta.INDEX_KEY, public val defaultValue: Value? = null, - public val readOnly: Boolean = false, public val attributes: Meta = Meta.EMPTY, ) { /** @@ -63,11 +62,12 @@ public data class MetaDescriptor( } public companion object { + public val EMPTY: MetaDescriptor = MetaDescriptor("Generic meta tree") internal const val ALLOWED_VALUES_KEY = "allowedValues" } } -public val MetaDescriptor.required: Boolean get() = valueRequirement == ValueRequirement.REQUIRED || children.values.any { required } +public val MetaDescriptor.required: Boolean get() = valueRestriction == ValueRestriction.REQUIRED || children.values.any { required } public val MetaDescriptor.allowedValues: List? get() = attributes[MetaDescriptor.ALLOWED_VALUES_KEY]?.value?.list @@ -80,9 +80,9 @@ public operator fun MetaDescriptor.get(name: Name): MetaDescriptor? = when (name public operator fun MetaDescriptor.get(name: String): MetaDescriptor? = get(name.parseAsName(true)) public fun MetaDescriptor.validate(value: Value?): Boolean = if (value == null) { - valueRequirement != ValueRequirement.REQUIRED + valueRestriction != ValueRestriction.REQUIRED } else { - if (valueRequirement == ValueRequirement.ABSENT) false + if (valueRestriction == ValueRestriction.ABSENT) false else { (valueTypes == null || value.type in valueTypes) && (allowedValues?.let { value in it } ?: true) } diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt index 524342b0..ae6c171a 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt @@ -8,20 +8,26 @@ import space.kscience.dataforge.names.first import space.kscience.dataforge.names.length import kotlin.collections.set -public class MetaDescriptorBuilder @PublishedApi internal constructor() { +public class MetaDescriptorBuilder @PublishedApi internal constructor() { public var info: String? = null public var children: MutableMap = linkedMapOf() public var multiple: Boolean = false - public var valueRequirement: ValueRequirement = ValueRequirement.NONE - public var readOnly: Boolean = false + public var valueRestriction: ValueRestriction = ValueRestriction.NONE - public var type: List? = null + public var valueTypes: List? = null - public fun type(primaryType: ValueType, vararg otherTypes: ValueType) { - type = listOf(primaryType, *otherTypes) + public fun valueType(primaryType: ValueType, vararg otherTypes: ValueType) { + valueTypes = listOf(primaryType, *otherTypes) } + /** + * A key for indexing values. Should be changed in case of the name clash. + */ public var indexKey: String = Meta.INDEX_KEY + + /** + * The default value + */ public var default: Value? = null public fun default(value: Any?) { @@ -42,6 +48,7 @@ public class MetaDescriptorBuilder @PublishedApi internal constructor() { children[name.first().body] = target target } + else -> { children.getOrPut(name.first().body) { MetaDescriptorBuilder() }.item(name.cutFirst(), block) } @@ -51,16 +58,17 @@ public class MetaDescriptorBuilder @PublishedApi internal constructor() { public fun node( name: Name, descriptor: MetaDescriptor, - block: MetaDescriptorBuilder.() -> Unit = {} + block: MetaDescriptorBuilder.() -> Unit = {}, ): MetaDescriptorBuilder = when (name.length) { 0 -> error("Can't set descriptor to root") 1 -> { val item = descriptor.toBuilder().apply { - valueRequirement = ValueRequirement.ABSENT + valueRestriction = ValueRestriction.ABSENT }.apply(block) children[name.first().body] = item item } + else -> children.getOrPut(name.first().body) { MetaDescriptorBuilder() }.node(name.cutFirst(), descriptor, block) @@ -79,14 +87,13 @@ public class MetaDescriptorBuilder @PublishedApi internal constructor() { @PublishedApi internal fun build(): MetaDescriptor = MetaDescriptor( - info = info, + description = info, children = children.mapValues { it.value.build() }, multiple = multiple, - valueRequirement = valueRequirement, - valueTypes = type, + valueRestriction = valueRestriction, + valueTypes = valueTypes, indexKey = indexKey, defaultValue = default, - readOnly = readOnly, attributes = attributes ) } @@ -104,9 +111,9 @@ public fun MetaDescriptorBuilder.value( name: Name, type: ValueType, vararg additionalTypes: ValueType, - block: MetaDescriptorBuilder.() -> Unit = {} + block: MetaDescriptorBuilder.() -> Unit = {}, ): MetaDescriptorBuilder = item(name) { - type(type, *additionalTypes) + valueType(type, *additionalTypes) block() } @@ -114,16 +121,16 @@ public fun MetaDescriptorBuilder.value( name: String, type: ValueType, vararg additionalTypes: ValueType, - block: MetaDescriptorBuilder.() -> Unit = {} + block: MetaDescriptorBuilder.() -> Unit = {}, ): MetaDescriptorBuilder = value(Name.parse(name), type, additionalTypes = additionalTypes, block) /** * Create and configure child value descriptor */ public fun MetaDescriptorBuilder.node( - name: Name, block: MetaDescriptorBuilder.() -> Unit + name: Name, block: MetaDescriptorBuilder.() -> Unit, ): MetaDescriptorBuilder = item(name) { - valueRequirement = ValueRequirement.ABSENT + valueRestriction = ValueRestriction.ABSENT block() } @@ -142,7 +149,7 @@ public fun MetaDescriptorBuilder.node( } public fun MetaDescriptorBuilder.required() { - valueRequirement = ValueRequirement.REQUIRED + valueRestriction = ValueRestriction.REQUIRED } public inline fun > MetaDescriptorBuilder.enum( @@ -158,11 +165,11 @@ public inline fun > MetaDescriptorBuilder.enum( } private fun MetaDescriptor.toBuilder(): MetaDescriptorBuilder = MetaDescriptorBuilder().apply { - info = this@toBuilder.info + info = this@toBuilder.description children = this@toBuilder.children.mapValuesTo(LinkedHashMap()) { it.value.toBuilder() } multiple = this@toBuilder.multiple - valueRequirement = this@toBuilder.valueRequirement - type = this@toBuilder.valueTypes + valueRestriction = this@toBuilder.valueRestriction + valueTypes = this@toBuilder.valueTypes indexKey = this@toBuilder.indexKey default = defaultValue attributes = this@toBuilder.attributes.toMutableMeta() diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/exoticValues.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/exoticValues.kt index 072cffdb..74952053 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/exoticValues.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/exoticValues.kt @@ -5,7 +5,7 @@ package space.kscience.dataforge.meta * A value built from string which content and type are parsed on-demand */ public class LazyParsedValue(public val string: String) : Value { - private val parsedValue by lazy { string.parseValue() } + private val parsedValue by lazy { Value.parse(string) } override val value: Any? get() = parsedValue.value override val type: ValueType get() = parsedValue.type diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaConverter.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaConverter.kt index 2ecc3393..0dfb63d7 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaConverter.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaConverter.kt @@ -1,79 +1,155 @@ package space.kscience.dataforge.meta.transformations import space.kscience.dataforge.meta.* +import space.kscience.dataforge.meta.descriptors.MetaDescriptor +import kotlin.reflect.KType +import kotlin.reflect.typeOf /** * A converter of generic object to and from [Meta] */ public interface MetaConverter { - public fun metaToObject(meta: Meta): T? + + /** + * Runtime type of [T] + */ + public val type: KType + + /** + * A descriptor for resulting meta + */ + public val descriptor: MetaDescriptor get() = MetaDescriptor.EMPTY + + /** + * Attempt conversion of [meta] to an object or return null if conversion failed + */ + public fun metaToObjectOrNull(meta: Meta): T? + + public fun metaToObject(meta: Meta): T = + metaToObjectOrNull(meta) ?: error("Meta $meta could not be interpreted by $this") + public fun objectToMeta(obj: T): Meta public companion object { public val meta: MetaConverter = object : MetaConverter { - override fun metaToObject(meta: Meta): Meta = meta + override val type: KType = typeOf() + + override fun metaToObjectOrNull(meta: Meta): Meta = meta override fun objectToMeta(obj: Meta): Meta = obj } public val value: MetaConverter = object : MetaConverter { - override fun metaToObject(meta: Meta): Value? = meta.value + override val type: KType = typeOf() + + override fun metaToObjectOrNull(meta: Meta): Value? = meta.value override fun objectToMeta(obj: Value): Meta = Meta(obj) } public val string: MetaConverter = object : MetaConverter { - override fun metaToObject(meta: Meta): String? = meta.string + override val type: KType = typeOf() + + override val descriptor: MetaDescriptor = MetaDescriptor { + valueType(ValueType.STRING) + } + + + override fun metaToObjectOrNull(meta: Meta): String? = meta.string override fun objectToMeta(obj: String): Meta = Meta(obj.asValue()) } public val boolean: MetaConverter = object : MetaConverter { - override fun metaToObject(meta: Meta): Boolean? = meta.boolean + override val type: KType = typeOf() + + override val descriptor: MetaDescriptor = MetaDescriptor { + valueType(ValueType.BOOLEAN) + } + + override fun metaToObjectOrNull(meta: Meta): Boolean? = meta.boolean override fun objectToMeta(obj: Boolean): Meta = Meta(obj.asValue()) } public val number: MetaConverter = object : MetaConverter { - override fun metaToObject(meta: Meta): Number? = meta.number + override val type: KType = typeOf() + + override val descriptor: MetaDescriptor = MetaDescriptor { + valueType(ValueType.NUMBER) + } + + override fun metaToObjectOrNull(meta: Meta): Number? = meta.number override fun objectToMeta(obj: Number): Meta = Meta(obj.asValue()) } public val double: MetaConverter = object : MetaConverter { - override fun metaToObject(meta: Meta): Double? = meta.double + override val type: KType = typeOf() + override val descriptor: MetaDescriptor = MetaDescriptor { + valueType(ValueType.NUMBER) + } + + override fun metaToObjectOrNull(meta: Meta): Double? = meta.double override fun objectToMeta(obj: Double): Meta = Meta(obj.asValue()) } public val float: MetaConverter = object : MetaConverter { - override fun metaToObject(meta: Meta): Float? = meta.float + override val type: KType = typeOf() + override val descriptor: MetaDescriptor = MetaDescriptor { + valueType(ValueType.NUMBER) + } + + override fun metaToObjectOrNull(meta: Meta): Float? = meta.float override fun objectToMeta(obj: Float): Meta = Meta(obj.asValue()) } public val int: MetaConverter = object : MetaConverter { - override fun metaToObject(meta: Meta): Int? = meta.int + override val type: KType = typeOf() + override val descriptor: MetaDescriptor = MetaDescriptor { + valueType(ValueType.NUMBER) + } + + override fun metaToObjectOrNull(meta: Meta): Int? = meta.int override fun objectToMeta(obj: Int): Meta = Meta(obj.asValue()) } public val long: MetaConverter = object : MetaConverter { - override fun metaToObject(meta: Meta): Long? = meta.long + override val type: KType = typeOf() + override val descriptor: MetaDescriptor = MetaDescriptor { + valueType(ValueType.NUMBER) + } + + override fun metaToObjectOrNull(meta: Meta): Long? = meta.long override fun objectToMeta(obj: Long): Meta = Meta(obj.asValue()) } public inline fun > enum(): MetaConverter = object : MetaConverter { + override val type: KType = typeOf() + + override val descriptor: MetaDescriptor = MetaDescriptor { + valueType(ValueType.STRING) + allowedValues(enumValues()) + } + @Suppress("USELESS_CAST") - override fun metaToObject(meta: Meta): E = meta.enum() as? E ?: error("The Item is not a Enum") + override fun metaToObjectOrNull(meta: Meta): E = meta.enum() as? E ?: error("The Item is not a Enum") override fun objectToMeta(obj: E): Meta = Meta(obj.asValue()) } public fun valueList( writer: (T) -> Value = { Value.of(it) }, - reader: (Value) -> T + reader: (Value) -> T, ): MetaConverter> = object : MetaConverter> { - override fun metaToObject(meta: Meta): List = - meta.value?.list?.map(reader) ?: error("The item is not a value list") + override val type: KType = typeOf>() + + override val descriptor: MetaDescriptor = MetaDescriptor { + valueType(ValueType.LIST) + } + + override fun metaToObjectOrNull(meta: Meta): List? = meta.value?.list?.map(reader) override fun objectToMeta(obj: List): Meta = Meta(obj.map(writer).asValue()) } diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaTransformation.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaTransformation.kt index b54f486a..d41365a6 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaTransformation.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaTransformation.kt @@ -42,7 +42,7 @@ public data class KeepTransformationRule(val selector: (Name) -> Boolean) : meta.nodeSequence().map { it.first }.filter(selector) override fun transformItem(name: Name, item: Meta?, target: MutableMeta) { - if (selector(name)) target.setMeta(name, item) + if (selector(name)) target.set(name, item) } } @@ -105,7 +105,7 @@ public value class MetaTransformation(private val transformations: Collection rule.selectItems(source).forEach { name -> rule.transformItem(name, source[name], this) @@ -174,7 +174,7 @@ public class MetaTransformationBuilder { public fun keep(regex: String) { transformations.add( RegexItemTransformationRule(regex.toRegex()) { name, _, Meta -> - setMeta(name, Meta) + set(name, Meta) }) } @@ -184,7 +184,7 @@ public class MetaTransformationBuilder { public fun move(from: Name, to: Name, operation: (Meta?) -> Meta? = { it }) { transformations.add( SingleItemTransformationRule(from) { _, item -> - setMeta(to, operation(item)) + set(to, operation(item)) } ) } diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/Type.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/DfId.kt similarity index 59% rename from dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/Type.kt rename to dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/DfId.kt index 3deaa63e..5d485e23 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/Type.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/DfId.kt @@ -2,9 +2,7 @@ package space.kscience.dataforge.misc /** * A text label for internal DataForge type classification. Alternative for mime container type. - * - * The DataForge type notation presumes that type `A.B.C` is the subtype of `A.B` */ @MustBeDocumented @Target(AnnotationTarget.CLASS) -public annotation class Type(val id: String) +public annotation class DfId(val id: String) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/Name.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/Name.kt index 6896437f..160ea3a1 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/Name.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/Name.kt @@ -134,6 +134,11 @@ public val Name.length: Int get() = tokens.size */ public fun Name.lastOrNull(): NameToken? = tokens.lastOrNull() +/** + * Last token or throw exception + */ +public fun Name.last(): NameToken = tokens.last() + /** * First token of the name or null if it is empty */ diff --git a/dataforge-meta/src/jvmTest/kotlin/space/kscience/dataforge/meta/JvmMutableMetaTest.kt b/dataforge-meta/src/jvmTest/kotlin/space/kscience/dataforge/meta/JvmMutableMetaTest.kt deleted file mode 100644 index 075a9e45..00000000 --- a/dataforge-meta/src/jvmTest/kotlin/space/kscience/dataforge/meta/JvmMutableMetaTest.kt +++ /dev/null @@ -1,15 +0,0 @@ -package space.kscience.dataforge.meta - -import org.junit.jupiter.api.Test -import kotlin.test.assertFails - -class JvmMutableMetaTest { - @Test - fun recursiveMeta(){ - val meta = MutableMeta { - "a" put 2 - } - - assertFails { meta["child.a"] = meta } - } -} \ No newline at end of file diff --git a/dataforge-scripting/README.md b/dataforge-scripting/README.md index c4d2caad..af79cc8f 100644 --- a/dataforge-scripting/README.md +++ b/dataforge-scripting/README.md @@ -6,27 +6,18 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-scripting:0.6.2-dev-2`. +The Maven coordinates of this project are `space.kscience:dataforge-scripting:0.7.0`. -**Gradle Groovy:** -```groovy -repositories { - maven { url 'https://repo.kotlin.link' } - mavenCentral() -} - -dependencies { - implementation 'space.kscience:dataforge-scripting:0.6.2-dev-2' -} -``` **Gradle Kotlin DSL:** ```kotlin repositories { maven("https://repo.kotlin.link") + //uncomment to access development builds + //maven("https://maven.pkg.jetbrains.space/spc/p/sci/dev") mavenCentral() } dependencies { - implementation("space.kscience:dataforge-scripting:0.6.2-dev-2") + implementation("space.kscience:dataforge-scripting:0.7.0") } ``` diff --git a/dataforge-workspace/README.md b/dataforge-workspace/README.md index 2aafb8df..c096699f 100644 --- a/dataforge-workspace/README.md +++ b/dataforge-workspace/README.md @@ -6,27 +6,18 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-workspace:0.6.2-dev-2`. +The Maven coordinates of this project are `space.kscience:dataforge-workspace:0.7.0`. -**Gradle Groovy:** -```groovy -repositories { - maven { url 'https://repo.kotlin.link' } - mavenCentral() -} - -dependencies { - implementation 'space.kscience:dataforge-workspace:0.6.2-dev-2' -} -``` **Gradle Kotlin DSL:** ```kotlin repositories { maven("https://repo.kotlin.link") + //uncomment to access development builds + //maven("https://maven.pkg.jetbrains.space/spc/p/sci/dev") mavenCentral() } dependencies { - implementation("space.kscience:dataforge-workspace:0.6.2-dev-2") + implementation("space.kscience:dataforge-workspace:0.7.0") } ``` diff --git a/dataforge-workspace/build.gradle.kts b/dataforge-workspace/build.gradle.kts index 28a633c8..ec117865 100644 --- a/dataforge-workspace/build.gradle.kts +++ b/dataforge-workspace/build.gradle.kts @@ -10,14 +10,18 @@ kscience{ useSerialization{ protobuf() } - dependencies { - api(projects.dataforgeContext) - api(projects.dataforgeData) - api(projects.dataforgeIo) + commonMain{ + dependencies { + api(projects.dataforgeContext) + api(projects.dataforgeData) + api(projects.dataforgeIo) + } } - dependencies(jvmTest){ - implementation(spclibs.logback.classic) - implementation(projects.dataforgeIo.dataforgeIoYaml) + jvmTest{ + dependencies { + implementation(spclibs.logback.classic) + implementation(projects.dataforgeIo.dataforgeIoYaml) + } } } diff --git a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Task.kt b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Task.kt index 782b925f..a1ef7be2 100644 --- a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Task.kt +++ b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Task.kt @@ -9,7 +9,7 @@ import space.kscience.dataforge.meta.MetaRepr import space.kscience.dataforge.meta.Specification import space.kscience.dataforge.meta.descriptors.Described import space.kscience.dataforge.meta.descriptors.MetaDescriptor -import space.kscience.dataforge.misc.Type +import space.kscience.dataforge.misc.DfId import space.kscience.dataforge.names.Name import space.kscience.dataforge.workspace.Task.Companion.TYPE import kotlin.reflect.KType @@ -19,7 +19,7 @@ import kotlin.reflect.typeOf * A configurable task that could be executed on a workspace. The [TaskResult] represents a lazy result of the task. * In general no computations should be made until the result is called. */ -@Type(TYPE) +@DfId(TYPE) public interface Task : Described { /** diff --git a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Workspace.kt b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Workspace.kt index 52f92037..ee00f539 100644 --- a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Workspace.kt +++ b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Workspace.kt @@ -6,7 +6,7 @@ import space.kscience.dataforge.data.DataSet import space.kscience.dataforge.data.asSequence import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MutableMeta -import space.kscience.dataforge.misc.Type +import space.kscience.dataforge.misc.DfId import space.kscience.dataforge.names.Name import space.kscience.dataforge.provider.Provider @@ -18,7 +18,7 @@ public interface DataSelector{ /** * An environment for pull-mode computation */ -@Type(Workspace.TYPE) +@DfId(Workspace.TYPE) public interface Workspace : ContextAware, Provider { /** * The whole data node for current workspace diff --git a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/taskBuilders.kt b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/taskBuilders.kt index 09791d15..bf3d5921 100644 --- a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/taskBuilders.kt +++ b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/taskBuilders.kt @@ -33,9 +33,12 @@ public suspend inline fun TaskResultBuild dependencyMeta: Meta = defaultDependencyMeta, selectorBuilder: P.() -> TaskReference, ): DataSet { - require(workspace.context.plugins.contains(plugin)){"Plugin $plugin is not loaded into $workspace"} + require(workspace.context.plugins.contains(plugin)) { "Plugin $plugin is not loaded into $workspace" } val taskReference: TaskReference = plugin.selectorBuilder() - return workspace.produce(plugin.name + taskReference.taskName, dependencyMeta) as TaskResult + val res = workspace.produce(plugin.name + taskReference.taskName, dependencyMeta) + //TODO add explicit check after https://youtrack.jetbrains.com/issue/KT-32956 + @Suppress("UNCHECKED_CAST") + return res as TaskResult } /** @@ -45,7 +48,7 @@ public suspend inline fun TaskResultBuild * @param dependencyMeta meta used for selector. The same meta is used for caching. By default, uses [defaultDependencyMeta]. * @param selectorBuilder a builder of task from the plugin. */ -public suspend inline fun TaskResultBuilder<*>.from( +public suspend inline fun TaskResultBuilder<*>.from( pluginFactory: PluginFactory

, dependencyMeta: Meta = defaultDependencyMeta, selectorBuilder: P.() -> TaskReference, @@ -53,7 +56,10 @@ public suspend inline fun TaskResultBuild val plugin = workspace.context.plugins[pluginFactory] ?: error("Plugin ${pluginFactory.tag} not loaded into workspace context") val taskReference: TaskReference = plugin.selectorBuilder() - return workspace.produce(plugin.name + taskReference.taskName, dependencyMeta) as TaskResult + val res = workspace.produce(plugin.name + taskReference.taskName, dependencyMeta) + //TODO explicit check after https://youtrack.jetbrains.com/issue/KT-32956 + @Suppress("UNCHECKED_CAST") + return res as TaskResult } public val TaskResultBuilder<*>.allData: DataSelector<*> @@ -79,7 +85,7 @@ public suspend inline fun TaskResultBuilder.pipeFr ) { from(selector, dependencyMeta).forEach { data -> val meta = data.meta.toMutableMeta().apply { - taskMeta[taskName]?.let { taskName.put(it) } + taskMeta[taskName]?.let { taskName.put(it) } dataMetaTransform(data.name) } diff --git a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCache.kt b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCache.kt index fdcb49a6..279e61a2 100644 --- a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCache.kt +++ b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCache.kt @@ -1,9 +1,6 @@ package space.kscience.dataforge.workspace -import io.ktor.utils.io.core.Input -import io.ktor.utils.io.core.Output -import io.ktor.utils.io.core.readBytes -import io.ktor.utils.io.core.writeFully +import kotlinx.io.* import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer import kotlinx.serialization.json.Json @@ -30,10 +27,10 @@ public class JsonIOFormat(override val type: KType) : IOFormat { @Suppress("UNCHECKED_CAST") private val serializer: KSerializer = serializer(type) as KSerializer - override fun readObject(input: Input): T = Json.decodeFromString(serializer, input.readUtf8String()) + override fun readFrom(source: Source): T = Json.decodeFromString(serializer, source.readString()) - override fun writeObject(output: Output, obj: T) { - output.writeUtf8String(Json.encodeToString(serializer, obj)) + override fun writeTo(sink: Sink, obj: T) { + sink.writeString(Json.encodeToString(serializer, obj)) } } @@ -43,10 +40,10 @@ public class ProtobufIOFormat(override val type: KType) : IOFormat { @Suppress("UNCHECKED_CAST") private val serializer: KSerializer = serializer(type) as KSerializer - override fun readObject(input: Input): T = ProtoBuf.decodeFromByteArray(serializer, input.readBytes()) + override fun readFrom(source: Source): T = ProtoBuf.decodeFromByteArray(serializer, source.readByteArray()) - override fun writeObject(output: Output, obj: T) { - output.writeFully(ProtoBuf.encodeToByteArray(serializer, obj)) + override fun writeTo(sink: Sink, obj: T) { + sink.write(ProtoBuf.encodeToByteArray(serializer, obj)) } } @@ -88,7 +85,7 @@ public class FileWorkspaceCache(public val cacheDirectory: Path) : WorkspaceCach val envelope = Envelope { meta = data.meta data { - writeObject(format, result) + writeWith(format, result) } } io.writeEnvelopeFile(path, envelope) diff --git a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/zipData.kt b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/zipData.kt index 706a2d0b..466552c2 100644 --- a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/zipData.kt +++ b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/zipData.kt @@ -1,13 +1,10 @@ package space.kscience.dataforge.workspace -import io.ktor.utils.io.streams.asOutput import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import space.kscience.dataforge.data.DataTree import space.kscience.dataforge.data.DataTreeItem -import space.kscience.dataforge.io.EnvelopeFormat -import space.kscience.dataforge.io.IOFormat -import space.kscience.dataforge.io.TaggedEnvelopeFormat +import space.kscience.dataforge.io.* import space.kscience.dataforge.misc.DFExperimental import java.nio.file.Files import java.nio.file.Path @@ -28,11 +25,15 @@ private suspend fun ZipOutputStream.writeNode( val envelope = treeItem.data.toEnvelope(dataFormat) val entry = ZipEntry(name) putNextEntry(entry) - asOutput().run { - envelopeFormat.writeObject(this, envelope) - flush() + + //TODO remove additional copy + val bytes = ByteArray { + writeWith(envelopeFormat, envelope) } + write(bytes) + } + is DataTreeItem.Node -> { val entry = ZipEntry("$name/") putNextEntry(entry) diff --git a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileDataTest.kt b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileDataTest.kt index 6ec31e0c..451c76f4 100644 --- a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileDataTest.kt +++ b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileDataTest.kt @@ -1,12 +1,18 @@ package space.kscience.dataforge.workspace -import io.ktor.utils.io.core.Input -import io.ktor.utils.io.core.Output import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.runTest +import kotlinx.io.Sink +import kotlinx.io.Source +import kotlinx.io.readString +import kotlinx.io.writeString import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Global import space.kscience.dataforge.data.* -import space.kscience.dataforge.io.* +import space.kscience.dataforge.io.Envelope +import space.kscience.dataforge.io.IOFormat +import space.kscience.dataforge.io.io +import space.kscience.dataforge.io.readEnvelopeFile import space.kscience.dataforge.io.yaml.YamlPlugin import space.kscience.dataforge.meta.get import space.kscience.dataforge.misc.DFExperimental @@ -36,11 +42,11 @@ class FileDataTest { object StringIOFormat : IOFormat { override val type: KType get() = typeOf() - override fun writeObject(output: Output, obj: String) { - output.writeUtf8String(obj) + override fun writeTo(sink: Sink, obj: String) { + sink.writeString(obj) } - override fun readObject(input: Input): String = input.readUtf8String() + override fun readFrom(source: Source): String = source.readString() } @Test @@ -59,9 +65,9 @@ class FileDataTest { @Test @DFExperimental - fun testZipWriteRead() = with(Global.io) { - val zip = Files.createTempFile("df_data_node", ".zip") - runBlocking { + fun testZipWriteRead() = runTest { + with(Global.io) { + val zip = Files.createTempFile("df_data_node", ".zip") dataNode.writeZip(zip, StringIOFormat) println(zip.toUri().toString()) val reconstructed = readDataDirectory(zip) { _, _ -> StringIOFormat } diff --git a/gradle.properties b/gradle.properties index 27743a30..31ef2f9a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,4 +6,5 @@ kotlin.mpp.stability.nowarn=true kotlin.incremental.js.ir=true kotlin.native.ignoreDisabledTargets=true -toolsVersion=0.14.9-kotlin-1.8.20 +toolsVersion=0.15.1-kotlin-1.9.21 +#kotlin.experimental.tryK2=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 15de9024..e411586a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index e9fb1b81..ca872038 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,7 +1,6 @@ rootProject.name = "dataforge-core" enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") -//enableFeaturePreview("VERSION_CATALOGS") pluginManagement { @@ -15,6 +14,7 @@ pluginManagement { } plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0" id("space.kscience.gradle.project") version toolsVersion id("space.kscience.gradle.mpp") version toolsVersion id("space.kscience.gradle.jvm") version toolsVersion