Optimized EnvelopeFormat generation API

This commit is contained in:
Alexander Nozik 2019-11-01 20:04:11 +03:00
parent 6f341f705a
commit 33b1de2865
4 changed files with 33 additions and 34 deletions

View File

@ -2,20 +2,18 @@ package hep.dataforge.io.yaml
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.io.* import hep.dataforge.io.*
import hep.dataforge.meta.* import hep.dataforge.meta.DFExperimental
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta
import kotlinx.io.core.* import kotlinx.io.core.*
import kotlinx.serialization.toUtf8Bytes import kotlinx.serialization.toUtf8Bytes
@DFExperimental @DFExperimental
class FrontMatterEnvelopeFormat( class FrontMatterEnvelopeFormat(
val io: IOPlugin, val io: IOPlugin,
val metaType: String = YamlMetaFormat.name.toString(),
meta: Meta = EmptyMeta meta: Meta = EmptyMeta
) : EnvelopeFormat { ) : EnvelopeFormat {
val metaFormat = io.metaFormat(metaType, meta)
?: error("Meta format with type $metaType could not be resolved in $io")
override fun Input.readPartial(): PartialEnvelope { override fun Input.readPartial(): PartialEnvelope {
var line: String = "" var line: String = ""
var offset = 0u var offset = 0u
@ -60,11 +58,12 @@ class FrontMatterEnvelopeFormat(
return SimpleEnvelope(meta, data) return SimpleEnvelope(meta, data)
} }
override fun Output.writeObject(obj: Envelope) { override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) {
val metaFormat = metaFormatFactory(formatMeta, io.context)
writeText("$SEPARATOR\r\n") writeText("$SEPARATOR\r\n")
metaFormat.run { writeObject(obj.meta) } metaFormat.run { writeObject(envelope.meta) }
writeText("$SEPARATOR\r\n") writeText("$SEPARATOR\r\n")
obj.data?.read { copyTo(this@writeObject) } envelope.data?.read { copyTo(this@writeEnvelope) }
} }
companion object : EnvelopeFormatFactory { companion object : EnvelopeFormatFactory {
@ -73,8 +72,7 @@ class FrontMatterEnvelopeFormat(
private val metaTypeRegex = "---(\\w*)\\s*".toRegex() private val metaTypeRegex = "---(\\w*)\\s*".toRegex()
override fun invoke(meta: Meta, context: Context): EnvelopeFormat { override fun invoke(meta: Meta, context: Context): EnvelopeFormat {
val metaFormatName: String = meta["name"].string ?: YamlMetaFormat.name.toString() return FrontMatterEnvelopeFormat(context.io, meta)
return FrontMatterEnvelopeFormat(context.io, metaFormatName, meta)
} }
override fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat? { override fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat? {

View File

@ -2,6 +2,7 @@ package hep.dataforge.io
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.io.EnvelopeFormatFactory.Companion.ENVELOPE_FORMAT_TYPE import hep.dataforge.io.EnvelopeFormatFactory.Companion.ENVELOPE_FORMAT_TYPE
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.asName import hep.dataforge.names.asName
@ -18,11 +19,15 @@ data class PartialEnvelope(val meta: Meta, val dataOffset: UInt, val dataSize: U
interface EnvelopeFormat : IOFormat<Envelope> { interface EnvelopeFormat : IOFormat<Envelope> {
val defaultMetaFormat: MetaFormatFactory get() = JsonMetaFormat
fun Input.readPartial(): PartialEnvelope fun Input.readPartial(): PartialEnvelope
fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta = EmptyMeta)
override fun Input.readObject(): Envelope override fun Input.readObject(): Envelope
override fun Output.writeObject(obj: Envelope) override fun Output.writeObject(obj: Envelope): Unit = writeEnvelope(obj, defaultMetaFormat)
} }
@Type(ENVELOPE_FORMAT_TYPE) @Type(ENVELOPE_FORMAT_TYPE)

View File

@ -13,12 +13,11 @@ import kotlinx.io.core.*
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
class TaggedEnvelopeFormat( class TaggedEnvelopeFormat(
val io: IOPlugin, val io: IOPlugin,
private val metaFormatKey: Short,
val version: VERSION = TaggedEnvelopeFormat.VERSION.DF02 val version: VERSION = TaggedEnvelopeFormat.VERSION.DF02
) : EnvelopeFormat { ) : EnvelopeFormat {
private val metaFormat = io.metaFormat(metaFormatKey) // private val metaFormat = io.metaFormat(metaFormatKey)
?: 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(): ByteReadPacket = buildPacket(24) { private fun Tag.toBytes(): ByteReadPacket = buildPacket(24) {
@ -37,13 +36,14 @@ class TaggedEnvelopeFormat(
writeText(END_SEQUENCE) writeText(END_SEQUENCE)
} }
override fun Output.writeObject(obj: Envelope) { override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) {
val metaBytes = metaFormat.writeBytes(obj.meta) val metaFormat = metaFormatFactory.invoke(formatMeta, io.context)
val tag = Tag(metaFormatKey, metaBytes.size.toUInt() + 2u, obj.data?.size ?: 0.toULong()) val metaBytes = metaFormat.writeBytes(envelope.meta)
val tag = Tag(metaFormatFactory.key, metaBytes.size.toUInt() + 2u, envelope.data?.size ?: 0.toULong())
writePacket(tag.toBytes()) writePacket(tag.toBytes())
writeFully(metaBytes) writeFully(metaBytes)
writeText("\r\n") writeText("\r\n")
obj.data?.read { copyTo(this@writeObject) } envelope.data?.read { copyTo(this@writeEnvelope) }
flush() flush()
} }
@ -102,7 +102,7 @@ class TaggedEnvelopeFormat(
val metaFormatFactory = io.metaFormatFactories.find { it.name == metaFormatName } val metaFormatFactory = io.metaFormatFactories.find { it.name == metaFormatName }
?: error("Meta format could not be resolved") ?: error("Meta format could not be resolved")
return TaggedEnvelopeFormat(io, metaFormatFactory.key) return TaggedEnvelopeFormat(io)
} }
private fun Input.readTag(version: VERSION): Tag { private fun Input.readTag(version: VERSION): Tag {
@ -124,9 +124,9 @@ class TaggedEnvelopeFormat(
override fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat? { override fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat? {
return try { return try {
val header = input.readTextExactBytes(6) val header = input.readTextExactBytes(6)
when(header.substring(2..5)){ when (header.substring(2..5)) {
VERSION.DF02.name-> TaggedEnvelopeFormat(io, JsonMetaFormat.key,VERSION.DF02) VERSION.DF02.name -> TaggedEnvelopeFormat(io, VERSION.DF02)
VERSION.DF03.name-> TaggedEnvelopeFormat(io, JsonMetaFormat.key,VERSION.DF03) VERSION.DF03.name -> TaggedEnvelopeFormat(io, VERSION.DF03)
else -> null else -> null
} }
} catch (ex: Exception) { } catch (ex: Exception) {

View File

@ -8,33 +8,30 @@ import kotlinx.serialization.toUtf8Bytes
class TaglessEnvelopeFormat( class TaglessEnvelopeFormat(
val io: IOPlugin, val io: IOPlugin,
val metaType: String = JsonMetaFormat.name.toString(),
meta: Meta = EmptyMeta meta: Meta = EmptyMeta
) : EnvelopeFormat { ) : EnvelopeFormat {
private val metaStart = meta[META_START_PROPERTY].string ?: DEFAULT_META_START private val metaStart = meta[META_START_PROPERTY].string ?: DEFAULT_META_START
private val dataStart = meta[DATA_START_PROPERTY].string ?: DEFAULT_DATA_START private val dataStart = meta[DATA_START_PROPERTY].string ?: DEFAULT_DATA_START
val metaFormat = io.metaFormat(metaType, meta)
?: error("Meta format with type $metaType could not be resolved in $io")
private fun Output.writeProperty(key: String, value: Any) { private fun Output.writeProperty(key: String, value: Any) {
writeText("#? $key: $value;\r\n") writeText("#? $key: $value;\r\n")
} }
override fun Output.writeObject(obj: Envelope) { override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta) {
val metaFormat = metaFormatFactory(formatMeta, io.context)
//printing header //printing header
writeText(TAGLESS_ENVELOPE_HEADER + "\r\n") writeText(TAGLESS_ENVELOPE_HEADER + "\r\n")
//printing all properties //printing all properties
writeProperty(META_TYPE_PROPERTY, metaType) writeProperty(META_TYPE_PROPERTY, metaFormatFactory.type)
//TODO add optional metaFormat properties //TODO add optional metaFormat properties
writeProperty(DATA_LENGTH_PROPERTY, obj.data?.size ?: 0) writeProperty(DATA_LENGTH_PROPERTY, envelope.data?.size ?: 0)
//Printing meta //Printing meta
if (!obj.meta.isEmpty()) { if (!envelope.meta.isEmpty()) {
val metaBytes = metaFormat.writeBytes(obj.meta) val metaBytes = metaFormat.writeBytes(envelope.meta)
writeProperty(META_LENGTH_PROPERTY, metaBytes.size) writeProperty(META_LENGTH_PROPERTY, metaBytes.size)
writeText(metaStart + "\r\n") writeText(metaStart + "\r\n")
writeFully(metaBytes) writeFully(metaBytes)
@ -42,7 +39,7 @@ class TaglessEnvelopeFormat(
} }
//Printing data //Printing data
obj.data?.let { data -> envelope.data?.let { data ->
writeText(dataStart + "\r\n") writeText(dataStart + "\r\n")
writeFully(data.toBytes()) writeFully(data.toBytes())
} }
@ -170,8 +167,7 @@ class TaglessEnvelopeFormat(
override val name = TAGLESS_ENVELOPE_TYPE.asName() override val name = TAGLESS_ENVELOPE_TYPE.asName()
override fun invoke(meta: Meta, context: Context): EnvelopeFormat { override fun invoke(meta: Meta, context: Context): EnvelopeFormat {
val metaFormatName: String = meta["name"].string ?: JsonMetaFormat.name.toString() return TaglessEnvelopeFormat(context.io, meta)
return TaglessEnvelopeFormat(context.io, metaFormatName, meta)
} }
val default by lazy { invoke() } val default by lazy { invoke() }