Fixed TaglessEnvelopeFormat resolution
This commit is contained in:
parent
d10bd40763
commit
4370a66164
@ -3,6 +3,7 @@ package hep.dataforge.io
|
|||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
import hep.dataforge.io.EnvelopeParts.FORMAT_META_KEY
|
import hep.dataforge.io.EnvelopeParts.FORMAT_META_KEY
|
||||||
import hep.dataforge.io.EnvelopeParts.FORMAT_NAME_KEY
|
import hep.dataforge.io.EnvelopeParts.FORMAT_NAME_KEY
|
||||||
|
import hep.dataforge.io.EnvelopeParts.INDEX_KEY
|
||||||
import hep.dataforge.io.EnvelopeParts.MULTIPART_DATA_TYPE
|
import hep.dataforge.io.EnvelopeParts.MULTIPART_DATA_TYPE
|
||||||
import hep.dataforge.io.EnvelopeParts.SIZE_KEY
|
import hep.dataforge.io.EnvelopeParts.SIZE_KEY
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
@ -13,6 +14,7 @@ import hep.dataforge.names.toName
|
|||||||
object EnvelopeParts {
|
object EnvelopeParts {
|
||||||
val MULTIPART_KEY = "multipart".asName()
|
val MULTIPART_KEY = "multipart".asName()
|
||||||
val SIZE_KEY = Envelope.ENVELOPE_NODE_KEY + MULTIPART_KEY + "size"
|
val SIZE_KEY = Envelope.ENVELOPE_NODE_KEY + MULTIPART_KEY + "size"
|
||||||
|
val INDEX_KEY = Envelope.ENVELOPE_NODE_KEY + MULTIPART_KEY + "index"
|
||||||
val FORMAT_NAME_KEY = Envelope.ENVELOPE_NODE_KEY + MULTIPART_KEY + "format"
|
val FORMAT_NAME_KEY = Envelope.ENVELOPE_NODE_KEY + MULTIPART_KEY + "format"
|
||||||
val FORMAT_META_KEY = Envelope.ENVELOPE_NODE_KEY + MULTIPART_KEY + "meta"
|
val FORMAT_META_KEY = Envelope.ENVELOPE_NODE_KEY + MULTIPART_KEY + "meta"
|
||||||
|
|
||||||
@ -37,8 +39,37 @@ fun EnvelopeBuilder.multipart(format: EnvelopeFormatFactory, envelopes: Collecti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun EnvelopeBuilder.multipart(formatFactory: EnvelopeFormatFactory, builder: suspend SequenceScope<Envelope>.() -> Unit) =
|
/**
|
||||||
multipart(formatFactory, sequence(builder).toList())
|
* Create a multipart partition in the envelope adding additional name-index mapping in meta
|
||||||
|
*/
|
||||||
|
@DFExperimental
|
||||||
|
fun EnvelopeBuilder.multipart(format: EnvelopeFormatFactory, envelopes: Map<String, Envelope>) {
|
||||||
|
dataType = MULTIPART_DATA_TYPE
|
||||||
|
meta {
|
||||||
|
SIZE_KEY put envelopes.size
|
||||||
|
FORMAT_NAME_KEY put format.name.toString()
|
||||||
|
}
|
||||||
|
data {
|
||||||
|
format.run {
|
||||||
|
var counter = 0
|
||||||
|
envelopes.forEach {(key, envelope)->
|
||||||
|
writeObject(envelope)
|
||||||
|
meta{
|
||||||
|
append(INDEX_KEY, buildMeta {
|
||||||
|
"key" put key
|
||||||
|
"index" put counter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun EnvelopeBuilder.multipart(
|
||||||
|
formatFactory: EnvelopeFormatFactory,
|
||||||
|
builder: suspend SequenceScope<Envelope>.() -> Unit
|
||||||
|
) = multipart(formatFactory, sequence(builder).toList())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If given envelope supports multipart data, return a sequence of those parts (could be empty). Otherwise return null.
|
* If given envelope supports multipart data, return a sequence of those parts (could be empty). Otherwise return null.
|
||||||
|
@ -52,7 +52,7 @@ class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
|
|||||||
|
|
||||||
companion object : PluginFactory<IOPlugin> {
|
companion object : PluginFactory<IOPlugin> {
|
||||||
val defaultMetaFormats: List<MetaFormatFactory> = listOf(JsonMetaFormat, BinaryMetaFormat)
|
val defaultMetaFormats: List<MetaFormatFactory> = listOf(JsonMetaFormat, BinaryMetaFormat)
|
||||||
val defaultEnvelopeFormats = listOf(TaggedEnvelopeFormat)
|
val defaultEnvelopeFormats = listOf(TaggedEnvelopeFormat, TaglessEnvelopeFormat)
|
||||||
|
|
||||||
override val tag: PluginTag = PluginTag("io", group = PluginTag.DATAFORGE_GROUP)
|
override val tag: PluginTag = PluginTag("io", group = PluginTag.DATAFORGE_GROUP)
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@ class TaglessEnvelopeFormat(
|
|||||||
writeText(dataStart + "\r\n")
|
writeText(dataStart + "\r\n")
|
||||||
writeFully(data.toBytes())
|
writeFully(data.toBytes())
|
||||||
}
|
}
|
||||||
|
flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun Input.readObject(): Envelope {
|
override fun Input.readObject(): Envelope {
|
||||||
@ -191,7 +192,7 @@ class TaglessEnvelopeFormat(
|
|||||||
return try {
|
return try {
|
||||||
val buffer = ByteArray(TAGLESS_ENVELOPE_HEADER.length)
|
val buffer = ByteArray(TAGLESS_ENVELOPE_HEADER.length)
|
||||||
input.readFully(buffer)
|
input.readFully(buffer)
|
||||||
return if (buffer.toString() == TAGLESS_ENVELOPE_HEADER) {
|
return if (String(buffer) == TAGLESS_ENVELOPE_HEADER) {
|
||||||
TaglessEnvelopeFormat(io)
|
TaglessEnvelopeFormat(io)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
|
@ -58,6 +58,24 @@ fun IOPlugin.writeMetaFile(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return inferred [EnvelopeFormat] if only one format could read given file. If no format accepts file, return null. If
|
||||||
|
* multiple formats accepts file, throw an error.
|
||||||
|
*/
|
||||||
|
fun IOPlugin.peekBinaryFormat(binary: Binary): EnvelopeFormat? {
|
||||||
|
val formats = envelopeFormatFactories.mapNotNull { factory ->
|
||||||
|
binary.read {
|
||||||
|
factory.peekFormat(this@peekBinaryFormat, this@read)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return when (formats.size) {
|
||||||
|
0 -> null
|
||||||
|
1 -> formats.first()
|
||||||
|
else -> error("Envelope format binary recognition clash")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read and envelope from file if the file exists, return null if file does not exist.
|
* Read and envelope from file if the file exists, return null if file does not exist.
|
||||||
*
|
*
|
||||||
@ -72,7 +90,11 @@ fun IOPlugin.writeMetaFile(
|
|||||||
* Return null otherwise.
|
* Return null otherwise.
|
||||||
*/
|
*/
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
fun IOPlugin.readEnvelopeFile(path: Path, readNonEnvelopes: Boolean = false): Envelope? {
|
fun IOPlugin.readEnvelopeFile(
|
||||||
|
path: Path,
|
||||||
|
readNonEnvelopes: Boolean = false,
|
||||||
|
formatPeeker: IOPlugin.(Binary) -> EnvelopeFormat? = IOPlugin::peekBinaryFormat
|
||||||
|
): Envelope? {
|
||||||
if (!Files.exists(path)) return null
|
if (!Files.exists(path)) return null
|
||||||
|
|
||||||
//read two-files directory
|
//read two-files directory
|
||||||
@ -99,24 +121,13 @@ fun IOPlugin.readEnvelopeFile(path: Path, readNonEnvelopes: Boolean = false): En
|
|||||||
|
|
||||||
val binary = path.asBinary()
|
val binary = path.asBinary()
|
||||||
|
|
||||||
val formats = envelopeFormatFactories.mapNotNull { factory ->
|
return formatPeeker(binary)?.run {
|
||||||
binary.read {
|
binary.read {
|
||||||
factory.peekFormat(this@readEnvelopeFile, this@read)
|
readObject()
|
||||||
}
|
}
|
||||||
}
|
} ?: if (readNonEnvelopes) { // if no format accepts file, read it as binary
|
||||||
return when (formats.size) {
|
SimpleEnvelope(Meta.empty, binary)
|
||||||
0 -> if (readNonEnvelopes) {
|
} else null
|
||||||
SimpleEnvelope(Meta.empty, binary)
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
1 -> formats.first().run {
|
|
||||||
binary.read {
|
|
||||||
readObject()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> error("Envelope format file recognition clash")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IOPlugin.writeEnvelopeFile(
|
fun IOPlugin.writeEnvelopeFile(
|
||||||
|
@ -22,10 +22,23 @@ class FileEnvelopeTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testFileWriteRead() {
|
fun testFileWriteRead() {
|
||||||
val tmpPath = Files.createTempFile("dataforge_test", ".df")
|
Global.io.run {
|
||||||
Global.io.writeEnvelopeFile(tmpPath,envelope)
|
val tmpPath = Files.createTempFile("dataforge_test", ".df")
|
||||||
println(tmpPath.toUri())
|
writeEnvelopeFile(tmpPath, envelope)
|
||||||
val restored: Envelope = Global.io.readEnvelopeFile(tmpPath)!!
|
println(tmpPath.toUri())
|
||||||
assertTrue { envelope.contentEquals(restored) }
|
val restored: Envelope = readEnvelopeFile(tmpPath)!!
|
||||||
|
assertTrue { envelope.contentEquals(restored) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFileWriteReadTagless() {
|
||||||
|
Global.io.run {
|
||||||
|
val tmpPath = Files.createTempFile("dataforge_test_tagless", ".df")
|
||||||
|
writeEnvelopeFile(tmpPath, envelope, format = TaglessEnvelopeFormat)
|
||||||
|
println(tmpPath.toUri())
|
||||||
|
val restored: Envelope = readEnvelopeFile(tmpPath)!!
|
||||||
|
assertTrue { envelope.contentEquals(restored) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user