Added peek format functionality to EnvelopeFormat
This commit is contained in:
parent
44a34eee40
commit
bf787fb5fc
@ -32,6 +32,12 @@ interface EnvelopeFormatFactory : IOFormatFactory<Envelope> {
|
|||||||
|
|
||||||
override fun invoke(meta: Meta, context: Context): EnvelopeFormat
|
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 {
|
companion object {
|
||||||
const val ENVELOPE_FORMAT_TYPE = "io.format.envelope"
|
const val ENVELOPE_FORMAT_TYPE = "io.format.envelope"
|
||||||
}
|
}
|
||||||
|
@ -10,20 +10,14 @@ import hep.dataforge.names.toName
|
|||||||
import kotlinx.io.core.*
|
import kotlinx.io.core.*
|
||||||
|
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
class TaggedEnvelopeFormat(val io: IOPlugin, meta: Meta) : EnvelopeFormat {
|
class TaggedEnvelopeFormat(
|
||||||
|
val io: IOPlugin,
|
||||||
private val metaFormat: MetaFormat
|
|
||||||
|
|
||||||
private val metaFormatKey: Short
|
private val metaFormatKey: Short
|
||||||
|
) : EnvelopeFormat {
|
||||||
|
|
||||||
init {
|
private val metaFormat =
|
||||||
val metaName = meta["name"].string?.toName() ?: JsonMetaFormat.name
|
io.metaFormat(metaFormatKey) ?: error("Meta format with key $metaFormatKey could not be resolved in $io")
|
||||||
val metaFormatFactory = io.metaFormatFactories.find { it.name == metaName }
|
|
||||||
?: error("Meta format could not be resolved")
|
|
||||||
|
|
||||||
metaFormat = metaFormatFactory(meta, io.context)
|
|
||||||
metaFormatKey = metaFormatFactory.key
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Tag.toBytes(): ByteReadPacket = buildPacket(24) {
|
private fun Tag.toBytes(): ByteReadPacket = buildPacket(24) {
|
||||||
writeText(START_SEQUENCE)
|
writeText(START_SEQUENCE)
|
||||||
@ -34,19 +28,6 @@ class TaggedEnvelopeFormat(val io: IOPlugin, meta: Meta) : EnvelopeFormat {
|
|||||||
writeText(END_SEQUENCE)
|
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) {
|
override fun Output.writeThis(obj: Envelope) {
|
||||||
val metaBytes = metaFormat.writeBytes(obj.meta)
|
val metaBytes = metaFormat.writeBytes(obj.meta)
|
||||||
val tag = Tag(metaFormatKey, metaBytes.size.toUInt(), obj.data?.size ?: 0.toULong())
|
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 val name: Name = super.name + VERSION
|
||||||
|
|
||||||
override fun invoke(meta: Meta, context: Context): EnvelopeFormat {
|
override fun invoke(meta: Meta, context: Context): EnvelopeFormat {
|
||||||
val plugin = context.plugins.fetch(IOPlugin)
|
val io = context.io
|
||||||
return TaggedEnvelopeFormat(plugin, meta)
|
|
||||||
|
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()
|
val default = invoke()
|
||||||
|
Loading…
Reference in New Issue
Block a user