diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ab4eac7..47dd5767 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,15 +3,20 @@ ## Unreleased ### Added +- Added separate `Meta`, `SealedMeta` and `ObservableMutableMeta` builders. ### Changed - Kotlin 1.9 +- `MutableMeta` builder now returns a simplified version of meta that does not hold listeners. +- Ktor-io is replaced with kotlinx-io. +- More concise names for read/write methods in IO. ### Deprecated ### Removed ### Fixed +- Memory leak in SealedMeta builder ### Security diff --git a/build.gradle.kts b/build.gradle.kts index bbab94eb..f15d4a8b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,7 +9,7 @@ plugins { allprojects { group = "space.kscience" - version = "0.6.2" + version = "0.6.3-dev-1" } subprojects { 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 736f3306..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 @@ -19,7 +19,7 @@ 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( @@ -39,20 +39,20 @@ public class FrontMatterEnvelopeFormat( offset += discardLine() - val meta = readMetaFormat.readObject(packet.asBinary()) + val meta = readMetaFormat.readFrom(packet.asBinary()) Envelope(meta, binary.view(offset)) } - override fun readObject(source: Source): Envelope = readObject(source.readBinary()) + override fun readFrom(source: Source): Envelope = readFrom(source.readBinary()) - override fun writeObject( + override fun writeTo( sink: Sink, obj: Envelope, ) { val metaFormat = metaFormatFactory.build(io.context, meta) val formatSuffix = if (metaFormat is YamlMetaFormat) "" else metaFormatFactory.shortName sink.writeString("$SEPARATOR${formatSuffix}\r\n") - metaFormat.run { metaFormat.writeObject(sink, obj.meta) } + metaFormat.run { metaFormat.writeTo(sink, obj.meta) } sink.writeString("$SEPARATOR\r\n") //Printing data obj.data?.let { data -> @@ -83,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( + override fun writeTo( sink: Sink, obj: Envelope, - ): Unit = default.writeObject(sink, obj) + ): Unit = default.writeTo(sink, obj) - override fun readObject(source: Source): Envelope = default.readObject(source) + 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/EnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeFormat.kt index d748d9f8..8a2a09b4 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 @@ -15,7 +15,7 @@ public interface EnvelopeFormat : IOFormat { override val type: KType get() = typeOf() } -public fun EnvelopeFormat.read(input: Source): Envelope = readObject(input) +public fun EnvelopeFormat.read(input: Source): Envelope = readFrom(input) @Type(ENVELOPE_FORMAT_TYPE) public interface EnvelopeFormatFactory : IOFormatFactory, EnvelopeFormat { 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 d0d00a9a..e51aa40a 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 @@ -23,9 +23,9 @@ public interface IOReader { */ public val type: KType - public fun readObject(source: Source): 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 { /** @@ -34,9 +34,9 @@ public interface IOReader { public val binary: IOReader = object : IOReader { override val type: KType = typeOf() - override fun readObject(source: Source): Binary = source.readByteArray().asBinary() + override fun readFrom(source: Source): Binary = source.readByteArray().asBinary() - override fun readObject(binary: Binary): Binary = binary + override fun readFrom(binary: Binary): Binary = binary } } } @@ -44,11 +44,11 @@ public interface IOReader { public inline fun IOReader(crossinline read: Source.() -> T): IOReader = object : IOReader { override val type: KType = typeOf() - override fun readObject(source: Source): T = source.read() + override fun readFrom(source: Source): T = source.read() } public fun interface IOWriter { - public fun writeObject(sink: Sink, obj: T) + public fun writeTo(sink: Sink, obj: T) } /** @@ -56,21 +56,20 @@ public fun interface IOWriter { */ public interface IOFormat : IOReader, IOWriter -public fun Source.readObject(format: IOReader): T = format.readObject(this@readObject) - -public fun IOFormat.readObjectFrom(binary: Binary): T = binary.read { - readObject(this) -} +public fun Source.readWith(format: IOReader): T = format.readFrom(this) /** * Read given binary as an object using given format */ public fun Binary.readWith(format: IOReader): T = read { - readObject(format) + readWith(format) } -public fun Sink.writeObject(format: IOWriter, obj: T): Unit = - format.writeObject(this@writeObject, obj) +/** + * Write an object to the [Sink] with given [format] + */ +public fun Sink.writeWith(format: IOWriter, obj: T): Unit = + format.writeTo(this, obj) @Type(IO_FORMAT_TYPE) @@ -87,7 +86,7 @@ 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 DoubleIOFormat : IOFormat, IOFormatFactory { override fun build(context: Context, meta: Meta): IOFormat = this @@ -96,9 +95,9 @@ public object DoubleIOFormat : IOFormat, IOFormatFactory { override val type: KType get() = typeOf() - override fun writeObject(sink: Sink, obj: Double) { + override fun writeTo(sink: Sink, obj: Double) { sink.writeLong(obj.toBits()) } - override fun readObject(source: Source): Double = Double.fromBits(source.readLong()) + override fun readFrom(source: Source): Double = Double.fromBits(source.readLong()) } \ No newline at end of file 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 25eb8f2f..dcffd657 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 @@ -23,11 +23,11 @@ public interface MetaFormat : IOFormat { override val type: KType get() = typeOf() - override fun writeObject(sink: Sink, obj: Meta) { + override fun writeTo(sink: Sink, obj: Meta) { writeMeta(sink, obj, null) } - override fun readObject(source: Source): Meta = readMeta(source) + override fun readFrom(source: Source): Meta = readMeta(source) public fun writeMeta( sink: Sink, @@ -57,13 +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 = readObject(StringSource(str).buffered()) +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 763c90b1..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 @@ -43,7 +43,7 @@ public class TaggedEnvelopeFormat( write(END_SEQUENCE) } - override fun writeObject( + override fun writeTo( sink: Sink, obj: Envelope, ) { @@ -65,7 +65,7 @@ public class TaggedEnvelopeFormat( * @param source an input to read from * @param formats a collection of meta formats to resolve */ - override fun readObject(source: Source): Envelope { + override fun readFrom(source: Source): Envelope { val tag = source.readTag(this.version) val metaFormat = io.resolveMetaFormat(tag.metaFormatKey) @@ -73,14 +73,14 @@ public class TaggedEnvelopeFormat( val metaBinary = source.readBinary(tag.metaSize.toInt()) - val meta: Meta = metaFormat.readObjectFrom(metaBinary) + val meta: Meta = metaFormat.readFrom(metaBinary) 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) @@ -88,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())) @@ -154,17 +154,17 @@ public class TaggedEnvelopeFormat( 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( + override fun writeTo( sink: Sink, obj: Envelope, ): Unit = default.run { - writeObject(sink, obj) + writeTo(sink, obj) } - override fun readObject(source: Source): Envelope = default.readObject(source) + 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 2d49a3c0..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 @@ -28,7 +28,7 @@ public class TaglessEnvelopeFormat( // writeFully("#? $key: $value;\r\n".encodeToByteArray()) // } - override fun writeObject( + override fun writeTo( sink: Sink, obj: Envelope, ) { @@ -54,7 +54,7 @@ public class TaglessEnvelopeFormat( } } - override fun readObject(source: Source): Envelope { + override fun readFrom(source: Source): Envelope { //read preamble source.discardWithSeparator( TAGLESS_ENVELOPE_HEADER, @@ -132,16 +132,16 @@ 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( + override fun writeTo( sink: Sink, obj: Envelope, ): Unit = default.run { - writeObject(sink, obj) + writeTo(sink, obj) } - override fun readObject(source: Source): Envelope = default.readObject(source) + override fun readFrom(source: Source): Envelope = default.readFrom(source) override fun peekFormat(io: IOPlugin, binary: Binary): EnvelopeFormat? { return try { 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 ff7f985d..4e4a7ff7 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 @@ -57,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") 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 3cc81b32..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 @@ -78,7 +78,7 @@ public fun Path.rewrite(block: Sink.() -> Unit): Unit { } @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 @@ -238,7 +238,7 @@ public fun IOPlugin.writeEnvelopeFile( envelopeFormat: EnvelopeFormat = TaggedEnvelopeFormat, ) { path.rewrite { - envelopeFormat.writeObject(this, envelope) + envelopeFormat.writeTo(this, envelope) } } 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 a637ad97..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 @@ -27,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: Source): T = Json.decodeFromString(serializer, input.readString()) + override fun readFrom(source: Source): T = Json.decodeFromString(serializer, source.readString()) - override fun writeObject(output: Sink, obj: T) { - output.writeString(Json.encodeToString(serializer, obj)) + override fun writeTo(sink: Sink, obj: T) { + sink.writeString(Json.encodeToString(serializer, obj)) } } @@ -40,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: Source): T = ProtoBuf.decodeFromByteArray(serializer, input.readByteArray()) + override fun readFrom(source: Source): T = ProtoBuf.decodeFromByteArray(serializer, source.readByteArray()) - override fun writeObject(output: Sink, obj: T) { - output.write(ProtoBuf.encodeToByteArray(serializer, obj)) + override fun writeTo(sink: Sink, obj: T) { + sink.write(ProtoBuf.encodeToByteArray(serializer, obj)) } } @@ -85,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 d23753a2..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 @@ -28,7 +28,7 @@ private suspend fun ZipOutputStream.writeNode( //TODO remove additional copy val bytes = ByteArray { - writeObject(envelopeFormat, envelope) + writeWith(envelopeFormat, envelope) } write(bytes) 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 313ea82e..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 @@ -9,7 +9,10 @@ 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 @@ -39,11 +42,11 @@ class FileDataTest { object StringIOFormat : IOFormat { override val type: KType get() = typeOf() - override fun writeObject(output: Sink, obj: String) { - output.writeString(obj) + override fun writeTo(sink: Sink, obj: String) { + sink.writeString(obj) } - override fun readObject(input: Source): String = input.readString() + override fun readFrom(source: Source): String = source.readString() } @Test