Added peek format functionality to EnvelopeFormat

This commit is contained in:
Alexander Nozik 2019-10-19 14:36:13 +03:00
parent 44a34eee40
commit bf787fb5fc
2 changed files with 40 additions and 26 deletions

View File

@ -32,6 +32,12 @@ interface EnvelopeFormatFactory : IOFormatFactory<Envelope> {
override fun invoke(meta: Meta, context: Context): EnvelopeFormat
/**
* Try to infer specific format from input and return null if the attempt is failed.
* This method does **not** return Input into initial state.
*/
fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat?
companion object {
const val ENVELOPE_FORMAT_TYPE = "io.format.envelope"
}

View File

@ -10,20 +10,14 @@ import hep.dataforge.names.toName
import kotlinx.io.core.*
@ExperimentalUnsignedTypes
class TaggedEnvelopeFormat(val io: IOPlugin, meta: Meta) : EnvelopeFormat {
private val metaFormat: MetaFormat
class TaggedEnvelopeFormat(
val io: IOPlugin,
private val metaFormatKey: Short
) : EnvelopeFormat {
init {
val metaName = meta["name"].string?.toName() ?: JsonMetaFormat.name
val metaFormatFactory = io.metaFormatFactories.find { it.name == metaName }
?: error("Meta format could not be resolved")
private val metaFormat =
io.metaFormat(metaFormatKey) ?: error("Meta format with key $metaFormatKey could not be resolved in $io")
metaFormat = metaFormatFactory(meta, io.context)
metaFormatKey = metaFormatFactory.key
}
private fun Tag.toBytes(): ByteReadPacket = buildPacket(24) {
writeText(START_SEQUENCE)
@ -34,19 +28,6 @@ class TaggedEnvelopeFormat(val io: IOPlugin, meta: Meta) : EnvelopeFormat {
writeText(END_SEQUENCE)
}
private fun Input.readTag(): Tag {
val start = readTextExactBytes(2)
if (start != START_SEQUENCE) error("The input is not an envelope")
val version = readTextExactBytes(4)
if (version != VERSION) error("Wrong version of DataForge: expected $VERSION but found $version")
val metaFormatKey = readShort()
val metaLength = readUInt()
val dataLength = readULong()
val end = readTextExactBytes(4)
if (end != END_SEQUENCE) error("The input is not an envelope")
return Tag(metaFormatKey, metaLength, dataLength)
}
override fun Output.writeThis(obj: Envelope) {
val metaBytes = metaFormat.writeBytes(obj.meta)
val tag = Tag(metaFormatKey, metaBytes.size.toUInt(), obj.data?.size ?: 0.toULong())
@ -101,8 +82,35 @@ class TaggedEnvelopeFormat(val io: IOPlugin, meta: Meta) : EnvelopeFormat {
override val name: Name = super.name + VERSION
override fun invoke(meta: Meta, context: Context): EnvelopeFormat {
val plugin = context.plugins.fetch(IOPlugin)
return TaggedEnvelopeFormat(plugin, meta)
val io = context.io
val metaFormatName = meta["name"].string?.toName() ?: JsonMetaFormat.name
val metaFormatFactory = io.metaFormatFactories.find { it.name == metaFormatName }
?: error("Meta format could not be resolved")
return TaggedEnvelopeFormat(io, metaFormatFactory.key)
}
private fun Input.readTag(): Tag {
val start = readTextExactBytes(2)
if (start != START_SEQUENCE) error("The input is not an envelope")
val version = readTextExactBytes(4)
if (version != VERSION) error("Wrong version of DataForge: expected $VERSION but found $version")
val metaFormatKey = readShort()
val metaLength = readUInt()
val dataLength = readULong()
val end = readTextExactBytes(4)
if (end != END_SEQUENCE) error("The input is not an envelope")
return Tag(metaFormatKey, metaLength, dataLength)
}
override fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat? {
return try {
val tag = input.readTag()
TaggedEnvelopeFormat(io, tag.metaFormatKey)
} catch (ex: Exception) {
null
}
}
val default = invoke()