Migrate to io-dev-6

This commit is contained in:
Alexander Nozik 2020-04-03 12:10:24 +03:00
parent 56e7d55450
commit 7efa19920b
24 changed files with 157 additions and 167 deletions

View File

@ -1,6 +1,6 @@
plugins { plugins {
val toolsVersion = "0.4.0" val toolsVersion = "0.4.1"
id("scientifik.mpp") version toolsVersion apply false id("scientifik.mpp") version toolsVersion apply false
id("scientifik.jvm") version toolsVersion apply false id("scientifik.jvm") version toolsVersion apply false
id("scientifik.publish") version toolsVersion apply false id("scientifik.publish") version toolsVersion apply false

View File

@ -11,7 +11,7 @@ serialization(sourceSet = TEST){
cbor() cbor()
} }
val ioVersion by rootProject.extra("0.2.0-npm-dev-4") val ioVersion by rootProject.extra("0.2.0-npm-dev-6")
kotlin { kotlin {
sourceSets { sourceSets {

View File

@ -7,7 +7,6 @@ import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import kotlinx.io.* import kotlinx.io.*
import kotlinx.io.text.readUtf8Line import kotlinx.io.text.readUtf8Line
import kotlinx.io.text.writeRawString
import kotlinx.io.text.writeUtf8String import kotlinx.io.text.writeUtf8String
import kotlinx.serialization.toUtf8Bytes import kotlinx.serialization.toUtf8Bytes
@ -29,7 +28,8 @@ class FrontMatterEnvelopeFormat(
metaTypeRegex.matchEntire(line)?.groupValues?.first() metaTypeRegex.matchEntire(line)?.groupValues?.first()
?.let { io.metaFormat(it) } ?: YamlMetaFormat ?.let { io.metaFormat(it) } ?: YamlMetaFormat
val meta = buildBytes { //TODO replace by preview
val meta = Binary {
do { do {
line = readUtf8Line() line = readUtf8Line()
writeUtf8String(line + "\r\n") writeUtf8String(line + "\r\n")
@ -53,7 +53,7 @@ class FrontMatterEnvelopeFormat(
metaTypeRegex.matchEntire(line)?.groupValues?.first() metaTypeRegex.matchEntire(line)?.groupValues?.first()
?.let { io.metaFormat(it) } ?: YamlMetaFormat ?.let { io.metaFormat(it) } ?: YamlMetaFormat
val meta = buildBytes { val meta = Binary {
do { do {
writeUtf8String(readUtf8Line() + "\r\n") writeUtf8String(readUtf8Line() + "\r\n")
} while (!line.startsWith(SEPARATOR)) } while (!line.startsWith(SEPARATOR))
@ -62,7 +62,7 @@ class FrontMatterEnvelopeFormat(
readMeta() readMeta()
} }
} }
val bytes = readRemaining() val bytes = readByteArray()
val data = bytes.asBinary() val data = bytes.asBinary()
return SimpleEnvelope(meta, data) return SimpleEnvelope(meta, data)
} }

View File

@ -10,24 +10,12 @@ import hep.dataforge.meta.toMap
import hep.dataforge.meta.toMeta import hep.dataforge.meta.toMeta
import kotlinx.io.Input import kotlinx.io.Input
import kotlinx.io.Output import kotlinx.io.Output
import kotlinx.io.asInputStream
import kotlinx.io.readUByte import kotlinx.io.readUByte
import kotlinx.io.text.writeUtf8String import kotlinx.io.text.writeUtf8String
import org.yaml.snakeyaml.Yaml import org.yaml.snakeyaml.Yaml
import java.io.InputStream import java.io.InputStream
private class InputAsStream(val input: Input) : InputStream() {
override fun read(): Int {
if (input.eof()) return -1
return input.readUByte().toInt()
}
override fun close() {
input.close()
}
}
private fun Input.asStream() = InputAsStream(this)
@DFExperimental @DFExperimental
class YamlMetaFormat(val meta: Meta) : MetaFormat { class YamlMetaFormat(val meta: Meta) : MetaFormat {
private val yaml = Yaml() private val yaml = Yaml()
@ -38,7 +26,7 @@ class YamlMetaFormat(val meta: Meta) : MetaFormat {
} }
override fun Input.readMeta(descriptor: NodeDescriptor?): Meta { override fun Input.readMeta(descriptor: NodeDescriptor?): Meta {
val map: Map<String, Any?> = yaml.load(asStream()) val map: Map<String, Any?> = yaml.load(asInputStream())
return map.toMeta(descriptor) return map.toMeta(descriptor)
} }

View File

@ -1,10 +1,7 @@
package hep.dataforge.io package hep.dataforge.io
import hep.dataforge.meta.* import hep.dataforge.meta.*
import kotlinx.io.ArrayBinary import kotlinx.io.*
import kotlinx.io.Binary
import kotlinx.io.ExperimentalIoApi
import kotlinx.io.Output
class EnvelopeBuilder { class EnvelopeBuilder {
private val metaBuilder = MetaBuilder() private val metaBuilder = MetaBuilder()
@ -36,7 +33,9 @@ class EnvelopeBuilder {
*/ */
@OptIn(ExperimentalIoApi::class) @OptIn(ExperimentalIoApi::class)
fun data(block: Output.() -> Unit) { fun data(block: Output.() -> Unit) {
data = ArrayBinary.write(builder = block) val arrayBuilder = ByteArrayOutput()
arrayBuilder.block()
data = arrayBuilder.toByteArray().asBinary()
} }
fun build() = SimpleEnvelope(metaBuilder.seal(), data) fun build() = SimpleEnvelope(metaBuilder.seal(), data)

View File

@ -11,8 +11,6 @@ import hep.dataforge.meta.*
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.names.toName import hep.dataforge.names.toName
import kotlinx.io.text.readRawString
import kotlinx.io.text.writeRawString
object EnvelopeParts { object EnvelopeParts {
val MULTIPART_KEY = "multipart".asName() val MULTIPART_KEY = "multipart".asName()

View File

@ -68,11 +68,7 @@ interface IOFormatFactory<T : Any> : Factory<IOFormat<T>>, Named {
} }
} }
fun <T : Any> IOFormat<T>.writeBytes(obj: T): Bytes = buildBytes { writeObject(obj) } fun <T : Any> IOFormat<T>.toBinary(obj: T): Binary = Binary { writeObject(obj) }
fun <T : Any> IOFormat<T>.writeByteArray(obj: T): ByteArray = buildBytes { writeObject(obj) }.toByteArray()
fun <T : Any> IOFormat<T>.readByteArray(array: ByteArray): T = array.asBinary().read { readObject() }
object DoubleIOFormat : IOFormat<Double>, IOFormatFactory<Double> { object DoubleIOFormat : IOFormat<Double>, IOFormatFactory<Double> {
override fun invoke(meta: Meta, context: Context): IOFormat<Double> = this override fun invoke(meta: Meta, context: Context): IOFormat<Double> = this

View File

@ -11,6 +11,7 @@ import hep.dataforge.meta.toJson
import hep.dataforge.meta.toMetaItem import hep.dataforge.meta.toMetaItem
import kotlinx.io.Input import kotlinx.io.Input
import kotlinx.io.Output import kotlinx.io.Output
import kotlinx.io.readByteArray
import kotlinx.io.text.readUtf8String import kotlinx.io.text.readUtf8String
import kotlinx.io.text.writeUtf8String import kotlinx.io.text.writeUtf8String
import kotlinx.serialization.UnstableDefault import kotlinx.serialization.UnstableDefault
@ -26,7 +27,7 @@ class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat {
} }
override fun Input.readMeta(descriptor: NodeDescriptor?): Meta { override fun Input.readMeta(descriptor: NodeDescriptor?): Meta {
val str = readUtf8String() val str = readByteArray().decodeToString()
val jsonElement = json.parseJson(str) val jsonElement = json.parseJson(str)
val item = jsonElement.toMetaItem(descriptor) val item = jsonElement.toMetaItem(descriptor)
return item.node ?: Meta.EMPTY return item.node ?: Meta.EMPTY

View File

@ -1,14 +1,17 @@
package hep.dataforge.io package hep.dataforge.io
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.io.MetaFormatFactory.Companion.META_FORMAT_TYPE import hep.dataforge.io.MetaFormatFactory.Companion.META_FORMAT_TYPE
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.provider.Type import hep.dataforge.provider.Type
import kotlinx.io.* import kotlinx.io.ByteArrayInput
import kotlinx.io.Input
import kotlinx.io.Output
import kotlinx.io.use
import kotlin.reflect.KClass import kotlin.reflect.KClass
/** /**
@ -44,14 +47,14 @@ interface MetaFormatFactory : IOFormatFactory<Meta>, MetaFormat {
} }
} }
fun Meta.toString(format: MetaFormat): String = buildBytes { fun Meta.toString(format: MetaFormat): String = buildByteArray {
format.run { writeObject(this@toString) } format.run { writeObject(this@toString) }
}.toByteArray().decodeToString() }.decodeToString()
fun Meta.toString(formatFactory: MetaFormatFactory): String = toString(formatFactory()) fun Meta.toString(formatFactory: MetaFormatFactory): String = toString(formatFactory())
fun MetaFormat.parse(str: String): Meta { fun MetaFormat.parse(str: String): Meta {
return str.encodeToByteArray().read { readObject() } return ByteArrayInput(str.encodeToByteArray()).use { it.readObject() }
} }
fun MetaFormatFactory.parse(str: String, formatMeta: Meta): Meta = invoke(formatMeta).parse(str) fun MetaFormatFactory.parse(str: String, formatMeta: Meta): Meta = invoke(formatMeta).parse(str)

View File

@ -8,8 +8,6 @@ import hep.dataforge.names.Name
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.names.toName import hep.dataforge.names.toName
import kotlinx.io.* import kotlinx.io.*
import kotlinx.io.text.readRawString
import kotlinx.io.text.writeRawString
@ExperimentalIoApi @ExperimentalIoApi
class TaggedEnvelopeFormat( class TaggedEnvelopeFormat(
@ -21,7 +19,7 @@ class TaggedEnvelopeFormat(
// ?: error("Meta format with key $metaFormatKey could not be resolved in $io") // ?: error("Meta format with key $metaFormatKey could not be resolved in $io")
private fun Tag.toBytes() = buildBytes(24) { private fun Tag.toBinary() = Binary(24) {
writeRawString(START_SEQUENCE) writeRawString(START_SEQUENCE)
writeRawString(version.name) writeRawString(version.name)
writeShort(metaFormatKey) writeShort(metaFormatKey)
@ -39,14 +37,10 @@ class TaggedEnvelopeFormat(
override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) { override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) {
val metaFormat = metaFormatFactory.invoke(formatMeta, io.context) val metaFormat = metaFormatFactory.invoke(formatMeta, io.context)
val metaBytes = metaFormat.writeBytes(envelope.meta) val metaBytes = metaFormat.toBinary(envelope.meta)
val actualSize: ULong = if (envelope.data == null) { val actualSize: ULong = (envelope.data?.size ?: 0).toULong()
0
} else {
envelope.data?.size ?: Binary.INFINITE
}.toULong()
val tag = Tag(metaFormatFactory.key, metaBytes.size.toUInt() + 2u, actualSize) val tag = Tag(metaFormatFactory.key, metaBytes.size.toUInt() + 2u, actualSize)
writeBinary(tag.toBytes()) writeBinary(tag.toBinary())
writeBinary(metaBytes) writeBinary(metaBytes)
writeRawString("\r\n") writeRawString("\r\n")
envelope.data?.let { envelope.data?.let {
@ -73,7 +67,7 @@ class TaggedEnvelopeFormat(
} }
} }
val data = ByteArray(tag.dataSize.toInt()).also { readArray(it) }.asBinary() val data = ByteArray(tag.dataSize.toInt()).also { readByteArray(it) }.asBinary()
return SimpleEnvelope(meta, data) return SimpleEnvelope(meta, data)
} }

View File

@ -4,9 +4,7 @@ import hep.dataforge.context.Context
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.names.asName import hep.dataforge.names.asName
import kotlinx.io.* import kotlinx.io.*
import kotlinx.io.text.readRawString
import kotlinx.io.text.readUtf8Line import kotlinx.io.text.readUtf8Line
import kotlinx.io.text.writeRawString
import kotlinx.io.text.writeUtf8String import kotlinx.io.text.writeUtf8String
@ExperimentalIoApi @ExperimentalIoApi
@ -31,17 +29,13 @@ class TaglessEnvelopeFormat(
//printing all properties //printing all properties
writeProperty(META_TYPE_PROPERTY, metaFormatFactory.shortName) writeProperty(META_TYPE_PROPERTY, metaFormatFactory.shortName)
//TODO add optional metaFormat properties //TODO add optional metaFormat properties
val actualSize: Int = if (envelope.data == null) { val actualSize: Int = envelope.data?.size ?: 0
0
} else {
envelope.data?.size ?: Binary.INFINITE
}
writeProperty(DATA_LENGTH_PROPERTY, actualSize) writeProperty(DATA_LENGTH_PROPERTY, actualSize)
//Printing meta //Printing meta
if (!envelope.meta.isEmpty()) { if (!envelope.meta.isEmpty()) {
val metaBytes = metaFormat.writeBytes(envelope.meta) val metaBytes = metaFormat.toBinary(envelope.meta)
writeProperty(META_LENGTH_PROPERTY, metaBytes.size + 2) writeProperty(META_LENGTH_PROPERTY, metaBytes.size + 2)
writeUtf8String(metaStart + "\r\n") writeUtf8String(metaStart + "\r\n")
writeBinary(metaBytes) writeBinary(metaBytes)
@ -71,7 +65,7 @@ class TaglessEnvelopeFormat(
properties[key] = value properties[key] = value
} }
//If can't read line, return envelope without data //If can't read line, return envelope without data
if (eof()) return SimpleEnvelope(Meta.EMPTY, null) if (exhausted()) return SimpleEnvelope(Meta.EMPTY, null)
line = readUtf8Line() line = readUtf8Line()
} }
@ -102,11 +96,11 @@ class TaglessEnvelopeFormat(
val data: Binary? = if (properties.containsKey(DATA_LENGTH_PROPERTY)) { val data: Binary? = if (properties.containsKey(DATA_LENGTH_PROPERTY)) {
val bytes = ByteArray(properties[DATA_LENGTH_PROPERTY]!!.toInt()) val bytes = ByteArray(properties[DATA_LENGTH_PROPERTY]!!.toInt())
readArray(bytes) readByteArray(bytes)
bytes.asBinary() bytes.asBinary()
} else { } else {
ArrayBinary.write { Binary {
writeInput(this@readObject) copyTo(this)
} }
} }

View File

@ -0,0 +1,22 @@
package hep.dataforge.io
import kotlinx.io.*
fun Output.writeRawString(str: String) {
str.forEach { writeByte(it.toByte()) }
}
fun Input.readRawString(size: Int): String {
val array = CharArray(size) { readByte().toChar() }
return String(array)
}
inline fun buildByteArray(expectedSize: Int = 16, block: Output.() -> Unit): ByteArray =
ByteArrayOutput(expectedSize).apply(block).toByteArray()
@Suppress("FunctionName")
inline fun Binary(expectedSize: Int = 16, block: Output.() -> Unit): Binary =
buildByteArray(expectedSize, block).asBinary()
@Deprecated("To be replaced by Binary.EMPTY",level = DeprecationLevel.WARNING)
val EmptyBinary = ByteArrayBinary(ByteArray(0))

View File

@ -23,7 +23,7 @@ class EnvelopeFormatTest {
@Test @Test
fun testTaggedFormat(){ fun testTaggedFormat(){
TaggedEnvelopeFormat.run { TaggedEnvelopeFormat.run {
val byteArray = this.writeByteArray(envelope) val byteArray = this.toByteArray(envelope)
//println(byteArray.decodeToString()) //println(byteArray.decodeToString())
val res = readByteArray(byteArray) val res = readByteArray(byteArray)
assertEquals(envelope.meta,res.meta) assertEquals(envelope.meta,res.meta)
@ -37,7 +37,7 @@ class EnvelopeFormatTest {
@Test @Test
fun testTaglessFormat(){ fun testTaglessFormat(){
TaglessEnvelopeFormat.run { TaglessEnvelopeFormat.run {
val byteArray = writeByteArray(envelope) val byteArray = toByteArray(envelope)
//println(byteArray.decodeToString()) //println(byteArray.decodeToString())
val res = readByteArray(byteArray) val res = readByteArray(byteArray)
assertEquals(envelope.meta,res.meta) assertEquals(envelope.meta,res.meta)

View File

@ -1,20 +1,19 @@
package hep.dataforge.io package hep.dataforge.io
import hep.dataforge.meta.* import hep.dataforge.meta.*
import kotlinx.io.Bytes import kotlinx.io.asBinary
import kotlinx.io.buildBytes
import kotlinx.serialization.json.JsonPrimitive import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.json import kotlinx.serialization.json.json
import kotlinx.serialization.json.jsonArray import kotlinx.serialization.json.jsonArray
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
fun Meta.toBytes(format: MetaFormat = JsonMetaFormat): Bytes = buildBytes { fun Meta.toByteArray(format: MetaFormat = JsonMetaFormat) = buildByteArray {
format.run { writeObject(this@toBytes) } format.run { writeObject(this@toByteArray) }
} }
fun MetaFormat.fromBytes(packet: Bytes): Meta { fun MetaFormat.fromByteArray(packet: ByteArray): Meta {
return packet.read { readObject() } return packet.asBinary().read { readObject() }
} }
class MetaFormatTest { class MetaFormatTest {
@ -28,8 +27,8 @@ class MetaFormatTest {
"array" put doubleArrayOf(1.0, 2.0, 3.0) "array" put doubleArrayOf(1.0, 2.0, 3.0)
} }
} }
val bytes = meta.toBytes(BinaryMetaFormat) val bytes = meta.toByteArray(BinaryMetaFormat)
val result = BinaryMetaFormat.fromBytes(bytes) val result = BinaryMetaFormat.fromByteArray(bytes)
assertEquals(meta, result) assertEquals(meta, result)
} }
@ -56,12 +55,12 @@ class MetaFormatTest {
} }
@Test @Test
fun testJsonToMeta(){ fun testJsonToMeta() {
val json = jsonArray{ val json = jsonArray {
//top level array //top level array
+jsonArray { +jsonArray {
+JsonPrimitive(88) +JsonPrimitive(88)
+json{ +json {
"c" to "aasdad" "c" to "aasdad"
"d" to true "d" to true
} }
@ -77,7 +76,7 @@ class MetaFormatTest {
assertEquals(true, meta["@value[0].@value[1].d"].boolean) assertEquals(true, meta["@value[0].@value[1].d"].boolean)
assertEquals("value", meta["@value[1]"].string) assertEquals("value", meta["@value[1]"].string)
assertEquals(listOf(1.0,2.0,3.0),meta["@value[2"].value?.list?.map{it.number.toDouble()}) assertEquals(listOf(1.0, 2.0, 3.0), meta["@value[2"].value?.list?.map { it.number.toDouble() })
} }
} }

View File

@ -3,7 +3,6 @@ package hep.dataforge.io
import hep.dataforge.meta.DFExperimental import hep.dataforge.meta.DFExperimental
import hep.dataforge.meta.get import hep.dataforge.meta.get
import hep.dataforge.meta.int import hep.dataforge.meta.int
import kotlinx.io.text.writeRawString
import kotlinx.io.text.writeUtf8String import kotlinx.io.text.writeUtf8String
import kotlin.test.Test import kotlin.test.Test
@ -33,9 +32,9 @@ class MultipartTest {
@Test @Test
fun testParts() { fun testParts() {
TaggedEnvelopeFormat.run { TaggedEnvelopeFormat.run {
val singleEnvelopeData = writeBytes(envelopes[0]) val singleEnvelopeData = toBinary(envelopes[0])
val singleEnvelopeSize = singleEnvelopeData.size val singleEnvelopeSize = singleEnvelopeData.size
val bytes = writeBytes(partsEnvelope) val bytes = toBinary(partsEnvelope)
assertTrue(5*singleEnvelopeSize < bytes.size) assertTrue(5*singleEnvelopeSize < bytes.size)
val reconstructed = bytes.readWith(this) val reconstructed = bytes.readWith(this)
val parts = reconstructed.parts()?.toList() ?: emptyList() val parts = reconstructed.parts()?.toList() ?: emptyList()

View File

@ -0,0 +1,7 @@
package hep.dataforge.io
import kotlinx.io.ByteArrayInput
import kotlinx.io.use
fun <T : Any> IOFormat<T>.toByteArray(obj: T): ByteArray = buildByteArray { writeObject(obj) }
fun <T : Any> IOFormat<T>.readByteArray(array: ByteArray): T = ByteArrayInput(array).use { it.readObject() }

View File

@ -1,22 +0,0 @@
package hep.dataforge.io
import hep.dataforge.meta.Meta
import kotlinx.io.Binary
import kotlinx.io.ExperimentalIoApi
import kotlinx.io.FileBinary
import kotlinx.io.read
import java.nio.file.Path
@ExperimentalIoApi
class FileEnvelope internal constructor(val path: Path, val format: EnvelopeFormat) : Envelope {
//TODO do not like this constructor. Hope to replace it later
private val partialEnvelope: PartialEnvelope = path.read {
format.run { readPartial() }
}
override val meta: Meta get() = partialEnvelope.meta
override val data: Binary? = FileBinary(path, partialEnvelope.dataOffset.toInt(), partialEnvelope.dataSize?.toInt())
}

View File

@ -8,9 +8,52 @@ import hep.dataforge.meta.isEmpty
import kotlinx.io.* import kotlinx.io.*
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.StandardOpenOption
import kotlin.reflect.full.isSuperclassOf import kotlin.reflect.full.isSuperclassOf
import kotlin.streams.asSequence import kotlin.streams.asSequence
fun <R> Path.read(block: Input.() -> R): R = asBinary().read(block = block)
/**
* Write a live output to a newly created file. If file does not exist, throws error
*/
fun Path.write(block: Output.() -> Unit): Unit {
val stream = Files.newOutputStream(this, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW)
stream.asOutput().use(block)
}
/**
* Create a new file or append to exiting one with given output [block]
*/
fun Path.append(block: Output.() -> Unit): Unit {
val stream = Files.newOutputStream(
this,
StandardOpenOption.WRITE, StandardOpenOption.APPEND, StandardOpenOption.CREATE
)
stream.asOutput().use(block)
}
/**
* Create a new file or replace existing one using given output [block]
*/
fun Path.rewrite(block: Output.() -> Unit): Unit {
val stream = Files.newOutputStream(
this,
StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE
)
stream.asOutput().use(block)
}
fun Path.readEnvelope(format: EnvelopeFormat): Envelope {
val partialEnvelope: PartialEnvelope = asBinary().read {
format.run { readPartial() }
}
val offset: Int = partialEnvelope.dataOffset.toInt()
val size: Int = partialEnvelope.dataSize?.toInt() ?: (Files.size(this).toInt() - offset)
val binary = FileBinary(this, offset, size)
return SimpleEnvelope(partialEnvelope.meta, binary)
}
/** /**
* Resolve IOFormat based on type * Resolve IOFormat based on type
*/ */
@ -37,7 +80,7 @@ fun IOPlugin.readMetaFile(path: Path, formatOverride: MetaFormat? = null, descri
val metaFormat = formatOverride ?: metaFormat(extension) ?: error("Can't resolve meta format $extension") val metaFormat = formatOverride ?: metaFormat(extension) ?: error("Can't resolve meta format $extension")
return metaFormat.run { return metaFormat.run {
actualPath.read{ actualPath.read {
readMeta(descriptor) readMeta(descriptor)
} }
} }
@ -59,7 +102,7 @@ fun IOPlugin.writeMetaFile(
path path
} }
metaFormat.run { metaFormat.run {
actualPath.write{ actualPath.write {
writeMeta(meta, descriptor) writeMeta(meta, descriptor)
} }
} }
@ -131,7 +174,7 @@ fun IOPlugin.readEnvelopeFile(
} }
return formatPeeker(path)?.let { format -> return formatPeeker(path)?.let { format ->
FileEnvelope(path, format) path.readEnvelope(format)
} ?: if (readNonEnvelopes) { // if no format accepts file, read it as binary } ?: if (readNonEnvelopes) { // if no format accepts file, read it as binary
SimpleEnvelope(Meta.EMPTY, path.asBinary()) SimpleEnvelope(Meta.EMPTY, path.asBinary())
} else null } else null
@ -156,7 +199,7 @@ fun IOPlugin.writeEnvelopeFile(
envelopeFormat: EnvelopeFormat = TaggedEnvelopeFormat, envelopeFormat: EnvelopeFormat = TaggedEnvelopeFormat,
metaFormat: MetaFormatFactory? = null metaFormat: MetaFormatFactory? = null
) { ) {
path.write { path.rewrite {
with(envelopeFormat) { with(envelopeFormat) {
writeEnvelope(envelope, metaFormat ?: envelopeFormat.defaultMetaFormat) writeEnvelope(envelope, metaFormat ?: envelopeFormat.defaultMetaFormat)
} }
@ -184,8 +227,8 @@ fun IOPlugin.writeEnvelopeDirectory(
val dataFile = path.resolve(IOPlugin.DATA_FILE_NAME) val dataFile = path.resolve(IOPlugin.DATA_FILE_NAME)
dataFile.write { dataFile.write {
envelope.data?.read { envelope.data?.read {
val copied = writeInput(this) val copied = copyTo(this@write)
if (envelope.data?.size != Binary.INFINITE && copied != envelope.data?.size) { if (copied != envelope.data?.size) {
error("The number of copied bytes does not equal data size") error("The number of copied bytes does not equal data size")
} }
} }

View File

@ -1,62 +1,45 @@
package hep.dataforge.io.tcp package hep.dataforge.io.tcp
import kotlinx.io.Input import kotlinx.io.*
import kotlinx.io.Output
import kotlinx.io.asBinary
import kotlinx.io.buffer.Buffer import kotlinx.io.buffer.Buffer
import kotlinx.io.buffer.get
import kotlinx.io.buffer.set import kotlinx.io.buffer.set
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
private class InputStreamInput(val source: InputStream, val waitForInput: Boolean = false) : Input() { private class BlockingStreamInput(val source: InputStream) : Input() {
override fun closeSource() { override fun closeSource() {
source.close() source.close()
} }
override fun fill(buffer: Buffer): Int { override fun fill(buffer: Buffer, startIndex: Int, endIndex: Int): Int {
if (waitForInput) {
while (source.available() == 0) { while (source.available() == 0) {
//block until input is available //block until input is available
} }
// Zero-copy attempt
if (buffer.buffer.hasArray()) {
val result = source.read(buffer.buffer.array(), startIndex, endIndex - startIndex)
return result.coerceAtLeast(0) // -1 when IS is closed
} }
var bufferPos = 0
do { for (i in startIndex until endIndex) {
val byte = source.read() val byte = source.read()
buffer[bufferPos] = byte.toByte() if (byte == -1) return (i - startIndex)
bufferPos++ buffer[i] = byte.toByte()
} while (byte > 0 && bufferPos < buffer.size && source.available() > 0) }
return bufferPos return endIndex - startIndex
} }
} }
private class OutputStreamOutput(val out: OutputStream) : Output() {
override fun flush(source: Buffer, length: Int) {
for (i in 0..length) {
out.write(source[i].toInt())
}
out.flush()
}
override fun closeSource() {
out.flush()
out.close()
}
}
fun <R> InputStream.read(size: Int, block: Input.() -> R): R { fun <R> InputStream.read(size: Int, block: Input.() -> R): R {
val buffer = ByteArray(size) val buffer = ByteArray(size)
read(buffer) read(buffer)
return buffer.asBinary().read(block) return buffer.asBinary().read(block = block)
} }
fun <R> InputStream.read(block: Input.() -> R): R = fun <R> InputStream.read(block: Input.() -> R): R = asInput().block()
InputStreamInput(this, false).block()
fun <R> InputStream.readBlocking(block: Input.() -> R): R = fun <R> InputStream.readBlocking(block: Input.() -> R): R = BlockingStreamInput(this).block()
InputStreamInput(this, true).block()
fun OutputStream.write(block: Output.() -> Unit) { inline fun OutputStream.write(block: Output.() -> Unit) {
OutputStreamOutput(this).block() asOutput().block()
} }

View File

@ -4,7 +4,7 @@ import hep.dataforge.context.Global
import hep.dataforge.io.Envelope import hep.dataforge.io.Envelope
import hep.dataforge.io.Responder import hep.dataforge.io.Responder
import hep.dataforge.io.TaggedEnvelopeFormat import hep.dataforge.io.TaggedEnvelopeFormat
import hep.dataforge.io.writeByteArray import hep.dataforge.io.toByteArray
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.io.writeDouble import kotlinx.io.writeDouble
@ -17,7 +17,7 @@ import kotlin.time.ExperimentalTime
@ExperimentalStdlibApi @ExperimentalStdlibApi
object EchoResponder : Responder { object EchoResponder : Responder {
override suspend fun respond(request: Envelope): Envelope { override suspend fun respond(request: Envelope): Envelope {
val string = TaggedEnvelopeFormat().run { writeByteArray(request).decodeToString() } val string = TaggedEnvelopeFormat().run { toByteArray(request).decodeToString() }
println("ECHO:") println("ECHO:")
println(string) println(string)
return request return request

View File

@ -23,9 +23,6 @@ open class Scheme() : Configurable, Described, MetaRepr {
var defaultProvider: (Name) -> MetaItem<*>? = { null } var defaultProvider: (Name) -> MetaItem<*>? = { null }
internal set internal set
final override var descriptor: NodeDescriptor? = null
internal set
override fun getDefaultItem(name: Name): MetaItem<*>? { override fun getDefaultItem(name: Name): MetaItem<*>? {
return defaultProvider(name) ?: descriptor?.get(name)?.defaultItem() return defaultProvider(name) ?: descriptor?.get(name)?.defaultItem()
} }
@ -78,15 +75,10 @@ open class SchemeSpec<T : Scheme>(val builder: () -> T) :
*/ */
open class MetaScheme( open class MetaScheme(
val meta: Meta, val meta: Meta,
descriptor: NodeDescriptor? = null, override val descriptor: NodeDescriptor? = null,
config: Config = Config() config: Config = Config()
) : Scheme(config, meta::get) { ) : Scheme(config, meta::get) {
init { override val defaultLayer: Meta get() = Laminate(meta, descriptor?.defaultItem().node)
this.descriptor = descriptor
}
override val defaultLayer: Meta
get() = Laminate(meta, descriptor?.defaultItem().node)
} }
fun Meta.asScheme() = fun Meta.asScheme() =

View File

@ -9,7 +9,6 @@ import kotlinx.coroutines.flow.toList
import kotlinx.io.Binary import kotlinx.io.Binary
import kotlinx.io.ExperimentalIoApi import kotlinx.io.ExperimentalIoApi
import kotlinx.io.Output import kotlinx.io.Output
import kotlinx.io.RandomAccessBinary
import kotlinx.io.text.forEachUtf8Line import kotlinx.io.text.forEachUtf8Line
import kotlinx.io.text.readUtf8Line import kotlinx.io.text.readUtf8Line
import kotlinx.io.text.readUtf8StringUntilDelimiter import kotlinx.io.text.readUtf8StringUntilDelimiter
@ -76,7 +75,7 @@ suspend fun TextRows.buildRowIndex(): List<Int> = indexFlow().toList()
@ExperimentalIoApi @ExperimentalIoApi
class TextTable( class TextTable(
override val header: ValueTableHeader, override val header: ValueTableHeader,
val binary: RandomAccessBinary, val binary: Binary,
val index: List<Int> val index: List<Int>
) : Table<Value> { ) : Table<Value> {
@ -99,7 +98,7 @@ class TextTable(
} }
companion object { companion object {
suspend operator fun invoke(header: ValueTableHeader, binary: RandomAccessBinary): TextTable { suspend operator fun invoke(header: ValueTableHeader, binary: Binary): TextTable {
val index = TextRows(header, binary).buildRowIndex() val index = TextRows(header, binary).buildRowIndex()
return TextTable(header, binary, index) return TextTable(header, binary, index)
} }

View File

@ -1,12 +1,13 @@
package hep.dataforge.tables.io package hep.dataforge.tables.io
import hep.dataforge.io.Binary
import hep.dataforge.io.EmptyBinary
import hep.dataforge.io.Envelope import hep.dataforge.io.Envelope
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.tables.SimpleColumnHeader import hep.dataforge.tables.SimpleColumnHeader
import hep.dataforge.tables.Table import hep.dataforge.tables.Table
import hep.dataforge.values.Value import hep.dataforge.values.Value
import kotlinx.io.ByteArrayOutput import kotlinx.io.ByteArrayOutput
import kotlinx.io.EmptyBinary
import kotlinx.io.ExperimentalIoApi import kotlinx.io.ExperimentalIoApi
import kotlinx.io.asBinary import kotlinx.io.asBinary

View File

@ -2,11 +2,7 @@ package hep.dataforge.workspace
import hep.dataforge.data.Data import hep.dataforge.data.Data
import hep.dataforge.data.await import hep.dataforge.data.await
import hep.dataforge.io.Envelope import hep.dataforge.io.*
import hep.dataforge.io.IOFormat
import hep.dataforge.io.SimpleEnvelope
import hep.dataforge.io.readWith
import kotlinx.io.ArrayBinary
import kotlin.reflect.KClass import kotlin.reflect.KClass
/** /**
@ -18,8 +14,6 @@ fun <T : Any> Envelope.toData(type: KClass<out T>, format: IOFormat<T>): Data<T>
suspend fun <T : Any> Data<T>.toEnvelope(format: IOFormat<T>): Envelope { suspend fun <T : Any> Data<T>.toEnvelope(format: IOFormat<T>): Envelope {
val obj = await() val obj = await()
val binary = ArrayBinary.write { val binary = format.toBinary(obj)
format.run { writeObject(obj) }
}
return SimpleEnvelope(meta, binary) return SimpleEnvelope(meta, binary)
} }