Fixed all IO issues (for now)
This commit is contained in:
parent
87ae41886b
commit
d3dd15884c
@ -1,9 +1,10 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("scientifik.mpp") version "0.2.1" apply false
|
id("scientifik.mpp") version "0.2.1" apply false
|
||||||
|
id("scientifik.jvm") version "0.2.1" apply false
|
||||||
id("scientifik.publish") version "0.2.1" apply false
|
id("scientifik.publish") version "0.2.1" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
val dataforgeVersion by extra("0.1.4-dev-6")
|
val dataforgeVersion by extra("0.1.4-dev-8")
|
||||||
|
|
||||||
val bintrayRepo by extra("dataforge")
|
val bintrayRepo by extra("dataforge")
|
||||||
val githubProject by extra("dataforge-core")
|
val githubProject by extra("dataforge-core")
|
||||||
|
9
dataforge-io/dataforge-io-yaml/build.gradle.kts
Normal file
9
dataforge-io/dataforge-io-yaml/build.gradle.kts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
plugins {
|
||||||
|
id("scientifik.jvm")
|
||||||
|
}
|
||||||
|
|
||||||
|
description = "YAML meta IO"
|
||||||
|
|
||||||
|
dependencies{
|
||||||
|
api(project(":dataforge-io"))
|
||||||
|
}
|
@ -11,26 +11,54 @@ import hep.dataforge.names.asName
|
|||||||
import hep.dataforge.provider.Type
|
import hep.dataforge.provider.Type
|
||||||
import hep.dataforge.values.Value
|
import hep.dataforge.values.Value
|
||||||
import kotlinx.io.core.*
|
import kotlinx.io.core.*
|
||||||
|
import kotlinx.io.pool.ObjectPool
|
||||||
import kotlinx.serialization.ImplicitReflectionSerializer
|
import kotlinx.serialization.ImplicitReflectionSerializer
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.cbor.Cbor
|
import kotlinx.serialization.cbor.Cbor
|
||||||
import kotlinx.serialization.serializer
|
import kotlinx.serialization.serializer
|
||||||
|
import kotlin.math.min
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* And interface for serialization facilities
|
* And interface for reading and writing objects into with IO streams
|
||||||
*/
|
*/
|
||||||
|
|
||||||
interface IOFormat<T : Any> {
|
interface IOFormat<T : Any> {
|
||||||
fun Output.writeThis(obj: T)
|
fun Output.writeThis(obj: T)
|
||||||
fun Input.readThis(): T
|
fun Input.readThis(): T
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : Any> IOFormat<T>.writePacket(obj: T): ByteReadPacket = buildPacket { writeThis(obj) }
|
fun <T : Any> Input.readWith(format: IOFormat<T>): T = format.run { readThis() }
|
||||||
fun <T : Any> IOFormat<T>.writeBytes(obj: T): ByteArray = buildPacket { writeThis(obj) }.readBytes()
|
fun <T : Any> Output.writeWith(format: IOFormat<T>, obj: T) = format.run { writeThis(obj) }
|
||||||
fun <T : Any> IOFormat<T>.readBytes(array: ByteArray): T = ByteReadPacket(array).readThis()
|
|
||||||
|
class ListIOFormat<T : Any>(val format: IOFormat<T>) : IOFormat<List<T>> {
|
||||||
|
override fun Output.writeThis(obj: List<T>) {
|
||||||
|
writeInt(obj.size)
|
||||||
|
format.run {
|
||||||
|
obj.forEach {
|
||||||
|
writeThis(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun Input.readThis(): List<T> {
|
||||||
|
val size = readInt()
|
||||||
|
return format.run {
|
||||||
|
List(size) { readThis() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val <T : Any> IOFormat<T>.list get() = ListIOFormat(this)
|
||||||
|
|
||||||
|
fun ObjectPool<IoBuffer>.fill(block: IoBuffer.() -> Unit): IoBuffer {
|
||||||
|
val buffer = borrow()
|
||||||
|
return try {
|
||||||
|
buffer.apply(block)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
//recycle(buffer)
|
||||||
|
throw ex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Type(IO_FORMAT_TYPE)
|
@Type(IO_FORMAT_TYPE)
|
||||||
interface IOFormatFactory<T : Any> : Factory<IOFormat<T>>, Named {
|
interface IOFormatFactory<T : Any> : Factory<IOFormat<T>>, Named {
|
||||||
@ -44,6 +72,65 @@ interface IOFormatFactory<T : Any> : Factory<IOFormat<T>>, Named {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("To be removed in io-2")
|
||||||
|
inline fun buildPacketWithoutPool(headerSizeHint: Int = 0, block: BytePacketBuilder.() -> Unit): ByteReadPacket {
|
||||||
|
val builder = BytePacketBuilder(headerSizeHint, IoBuffer.NoPool)
|
||||||
|
block(builder)
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
//@Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_OVERRIDE")
|
||||||
|
//internal fun <R> Input.useAtMost(most: Int, reader: Input.() -> R): R {
|
||||||
|
// val limitedInput: Input = object : AbstractInput(
|
||||||
|
// IoBuffer.Pool.borrow(),
|
||||||
|
// remaining = most.toLong(),
|
||||||
|
// pool = IoBuffer.Pool
|
||||||
|
// ) {
|
||||||
|
// var read = 0
|
||||||
|
// override fun closeSource() {
|
||||||
|
// this@useAtMost.close()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun fill(): IoBuffer? {
|
||||||
|
// if (read >= most) return null
|
||||||
|
// return IoBuffer.Pool.fill {
|
||||||
|
// reserveEndGap(IoBuffer.ReservedSize)
|
||||||
|
// read += this@useAtMost.peekTo(this, max = most - read)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// return limitedInput.reader()
|
||||||
|
//}
|
||||||
|
|
||||||
|
fun <T : Any> IOFormat<T>.writePacket(obj: T): ByteReadPacket = buildPacket { writeThis(obj) }
|
||||||
|
fun <T : Any> IOFormat<T>.writeBytes(obj: T): ByteArray = buildPacket { writeThis(obj) }.readBytes()
|
||||||
|
fun <T : Any> IOFormat<T>.readBytes(array: ByteArray): T {
|
||||||
|
//= ByteReadPacket(array).readThis()
|
||||||
|
val byteArrayInput: Input = object : AbstractInput(
|
||||||
|
IoBuffer.Pool.borrow(),
|
||||||
|
remaining = array.size.toLong(),
|
||||||
|
pool = IoBuffer.Pool
|
||||||
|
) {
|
||||||
|
var written = 0
|
||||||
|
override fun closeSource() {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fill(): IoBuffer? {
|
||||||
|
if (array.size - written <= 0) return null
|
||||||
|
|
||||||
|
return IoBuffer.Pool.fill {
|
||||||
|
reserveEndGap(IoBuffer.ReservedSize)
|
||||||
|
val toWrite = min(capacity, array.size - written)
|
||||||
|
writeFully(array, written, toWrite)
|
||||||
|
written += toWrite
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return byteArrayInput.readThis()
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
|
@ -24,7 +24,7 @@ import kotlin.collections.component2
|
|||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
|
|
||||||
|
|
||||||
class JsonMetaFormat(private val json: Json = Json.plain) : MetaFormat {
|
class JsonMetaFormat(private val json: Json = Json.indented) : MetaFormat {
|
||||||
|
|
||||||
override fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor?) {
|
override fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor?) {
|
||||||
val jsonObject = meta.toJson(descriptor)
|
val jsonObject = meta.toJson(descriptor)
|
||||||
@ -34,12 +34,7 @@ class JsonMetaFormat(private val json: Json = Json.plain) : MetaFormat {
|
|||||||
override fun Input.readMeta(descriptor: NodeDescriptor?): Meta {
|
override fun Input.readMeta(descriptor: NodeDescriptor?): Meta {
|
||||||
val str = readText()
|
val str = readText()
|
||||||
val jsonElement = json.parseJson(str)
|
val jsonElement = json.parseJson(str)
|
||||||
|
|
||||||
if (jsonElement is JsonObject) {
|
|
||||||
return jsonElement.toMeta()
|
return jsonElement.toMeta()
|
||||||
} else {
|
|
||||||
TODO("Non-object root not supported")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : MetaFormatFactory {
|
companion object : MetaFormatFactory {
|
||||||
@ -92,7 +87,12 @@ fun Meta.toJson(descriptor: NodeDescriptor? = null): JsonObject {
|
|||||||
return JsonObject(map)
|
return JsonObject(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun JsonObject.toMeta(descriptor: NodeDescriptor? = null): JsonMeta = JsonMeta(this, descriptor)
|
fun JsonElement.toMeta(descriptor: NodeDescriptor? = null): Meta {
|
||||||
|
return when (val item = toMetaItem(descriptor)) {
|
||||||
|
is MetaItem.NodeItem<*> -> item.node
|
||||||
|
is MetaItem.ValueItem ->item.value.toMeta()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun JsonPrimitive.toValue(descriptor: ValueDescriptor?): Value {
|
fun JsonPrimitive.toValue(descriptor: ValueDescriptor?): Value {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
@ -107,7 +107,7 @@ fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem<JsonMet
|
|||||||
MetaItem.ValueItem(value)
|
MetaItem.ValueItem(value)
|
||||||
}
|
}
|
||||||
is JsonObject -> {
|
is JsonObject -> {
|
||||||
val meta = toMeta(descriptor as? NodeDescriptor)
|
val meta = JsonMeta(this, descriptor as? NodeDescriptor)
|
||||||
MetaItem.NodeItem(meta)
|
MetaItem.NodeItem(meta)
|
||||||
}
|
}
|
||||||
is JsonArray -> {
|
is JsonArray -> {
|
||||||
@ -143,7 +143,7 @@ class JsonMeta(val json: JsonObject, val descriptor: NodeDescriptor? = null) : M
|
|||||||
this[name] = MetaItem.ValueItem(value.toValue(itemDescriptor as? ValueDescriptor)) as MetaItem<JsonMeta>
|
this[name] = MetaItem.ValueItem(value.toValue(itemDescriptor as? ValueDescriptor)) as MetaItem<JsonMeta>
|
||||||
}
|
}
|
||||||
is JsonObject -> {
|
is JsonObject -> {
|
||||||
this[name] = MetaItem.NodeItem(value.toMeta(itemDescriptor as? NodeDescriptor))
|
this[name] = MetaItem.NodeItem(JsonMeta(value, itemDescriptor as? NodeDescriptor))
|
||||||
}
|
}
|
||||||
is JsonArray -> {
|
is JsonArray -> {
|
||||||
when {
|
when {
|
||||||
|
@ -20,7 +20,7 @@ interface MetaFormat : IOFormat<Meta> {
|
|||||||
writeMeta(obj, null)
|
writeMeta(obj, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun Input.readThis(): Meta = readMeta(null)
|
override fun Input.readThis(): Meta = readMeta()
|
||||||
|
|
||||||
fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor? = null)
|
fun Output.writeMeta(meta: Meta, descriptor: NodeDescriptor? = null)
|
||||||
fun Input.readMeta(descriptor: NodeDescriptor? = null): Meta
|
fun Input.readMeta(descriptor: NodeDescriptor? = null): Meta
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
package hep.dataforge.io
|
|
||||||
|
|
||||||
import hep.dataforge.meta.Config
|
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.meta.toConfig
|
|
||||||
import hep.dataforge.names.Name
|
|
||||||
import hep.dataforge.names.NameToken
|
|
||||||
import hep.dataforge.names.toName
|
|
||||||
import kotlinx.serialization.*
|
|
||||||
import kotlinx.serialization.internal.StringDescriptor
|
|
||||||
import kotlinx.serialization.json.JsonObjectSerializer
|
|
||||||
|
|
||||||
@Serializer(Name::class)
|
|
||||||
object NameSerializer : KSerializer<Name> {
|
|
||||||
override val descriptor: SerialDescriptor = StringDescriptor.withName("Name")
|
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): Name {
|
|
||||||
return decoder.decodeString().toName()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, obj: Name) {
|
|
||||||
encoder.encodeString(obj.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Serializer(NameToken::class)
|
|
||||||
object NameTokenSerializer : KSerializer<NameToken> {
|
|
||||||
override val descriptor: SerialDescriptor = StringDescriptor.withName("NameToken")
|
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): NameToken {
|
|
||||||
return decoder.decodeString().toName().first()!!
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, obj: NameToken) {
|
|
||||||
encoder.encodeString(obj.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialized for meta
|
|
||||||
*/
|
|
||||||
@Serializer(Meta::class)
|
|
||||||
object MetaSerializer : KSerializer<Meta> {
|
|
||||||
override val descriptor: SerialDescriptor = JsonObjectSerializer.descriptor
|
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): Meta {
|
|
||||||
//currently just delegates serialization to json serializer
|
|
||||||
return JsonObjectSerializer.deserialize(decoder).toMeta()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, obj: Meta) {
|
|
||||||
JsonObjectSerializer.serialize(encoder, obj.toJson())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Serializer(Config::class)
|
|
||||||
object ConfigSerializer : KSerializer<Config> {
|
|
||||||
override val descriptor: SerialDescriptor = JsonObjectSerializer.descriptor
|
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): Config {
|
|
||||||
return JsonObjectSerializer.deserialize(decoder).toMeta().toConfig()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, obj: Config) {
|
|
||||||
JsonObjectSerializer.serialize(encoder, obj.toJson())
|
|
||||||
}
|
|
||||||
}
|
|
@ -70,10 +70,10 @@ class TaglessEnvelopeFormat(
|
|||||||
|
|
||||||
if (line.startsWith(metaStart)) {
|
if (line.startsWith(metaStart)) {
|
||||||
val metaFormat = properties[META_TYPE_PROPERTY]?.let { io.metaFormat(it) } ?: JsonMetaFormat.default
|
val metaFormat = properties[META_TYPE_PROPERTY]?.let { io.metaFormat(it) } ?: JsonMetaFormat.default
|
||||||
meta = if (properties.containsKey(META_LENGTH_PROPERTY)) {
|
val metaSize = properties.get(META_LENGTH_PROPERTY)?.toInt()
|
||||||
val bytes = ByteArray(properties[META_LENGTH_PROPERTY]!!.toInt())
|
meta = if (metaSize != null) {
|
||||||
readFully(bytes)
|
val metaPacket = ByteReadPacket(readBytes(metaSize))
|
||||||
metaFormat.readBytes(bytes)
|
metaFormat.run { metaPacket.readThis() }
|
||||||
} else {
|
} else {
|
||||||
metaFormat.run {
|
metaFormat.run {
|
||||||
readThis()
|
readThis()
|
||||||
@ -123,11 +123,12 @@ class TaglessEnvelopeFormat(
|
|||||||
|
|
||||||
if (line.startsWith(metaStart)) {
|
if (line.startsWith(metaStart)) {
|
||||||
val metaFormat = properties[META_TYPE_PROPERTY]?.let { io.metaFormat(it) } ?: JsonMetaFormat.default
|
val metaFormat = properties[META_TYPE_PROPERTY]?.let { io.metaFormat(it) } ?: JsonMetaFormat.default
|
||||||
meta = if (properties.containsKey(META_LENGTH_PROPERTY)) {
|
|
||||||
val bytes = ByteArray(properties[META_LENGTH_PROPERTY]!!.toInt())
|
val metaSize = properties.get(META_LENGTH_PROPERTY)?.toInt()
|
||||||
readFully(bytes)
|
meta = if (metaSize != null) {
|
||||||
offset += bytes.size.toUInt()
|
val metaPacket = ByteReadPacket(readBytes(metaSize))
|
||||||
metaFormat.readBytes(bytes)
|
offset += metaSize.toUInt()
|
||||||
|
metaFormat.run { metaPacket.readThis() }
|
||||||
} else {
|
} else {
|
||||||
error("Can't partially read an envelope with undefined meta size")
|
error("Can't partially read an envelope with undefined meta size")
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,135 @@
|
|||||||
|
package hep.dataforge.io
|
||||||
|
|
||||||
|
import hep.dataforge.io.serialization.descriptor
|
||||||
|
import hep.dataforge.meta.*
|
||||||
|
import hep.dataforge.names.NameToken
|
||||||
|
import hep.dataforge.values.*
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
import kotlinx.serialization.internal.*
|
||||||
|
import kotlinx.serialization.json.JsonInput
|
||||||
|
import kotlinx.serialization.json.JsonObjectSerializer
|
||||||
|
import kotlinx.serialization.json.JsonOutput
|
||||||
|
|
||||||
|
|
||||||
|
@Serializer(Value::class)
|
||||||
|
object ValueSerializer : KSerializer<Value> {
|
||||||
|
private val valueTypeSerializer = EnumSerializer(ValueType::class)
|
||||||
|
private val listSerializer by lazy { ArrayListSerializer(ValueSerializer)}
|
||||||
|
|
||||||
|
override val descriptor: SerialDescriptor = descriptor("Value") {
|
||||||
|
element("isList")
|
||||||
|
element("valueType")
|
||||||
|
element("value")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Decoder.decodeValue(): Value {
|
||||||
|
return when (decode(valueTypeSerializer)) {
|
||||||
|
ValueType.NULL -> Null
|
||||||
|
ValueType.NUMBER -> decodeDouble().asValue() //TODO differentiate?
|
||||||
|
ValueType.BOOLEAN -> decodeBoolean().asValue()
|
||||||
|
ValueType.STRING -> decodeString().asValue()
|
||||||
|
else -> decodeString().parseValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): Value {
|
||||||
|
val isList = decoder.decodeBoolean()
|
||||||
|
return if (isList) {
|
||||||
|
listSerializer.deserialize(decoder).asValue()
|
||||||
|
} else {
|
||||||
|
decoder.decodeValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Encoder.encodeValue(value: Value) {
|
||||||
|
encode(valueTypeSerializer, value.type)
|
||||||
|
when (value.type) {
|
||||||
|
ValueType.NULL -> {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
ValueType.NUMBER -> encodeDouble(value.double)
|
||||||
|
ValueType.BOOLEAN -> encodeBoolean(value.boolean)
|
||||||
|
ValueType.STRING -> encodeString(value.string)
|
||||||
|
else -> encodeString(value.string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, obj: Value) {
|
||||||
|
encoder.encodeBoolean(obj.isList())
|
||||||
|
if (obj.isList()) {
|
||||||
|
listSerializer.serialize(encoder, obj.list)
|
||||||
|
} else {
|
||||||
|
encoder.encodeValue(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializer(MetaItem::class)
|
||||||
|
object MetaItemSerializer : KSerializer<MetaItem<*>> {
|
||||||
|
override val descriptor: SerialDescriptor = descriptor("MetaItem") {
|
||||||
|
element("isNode")
|
||||||
|
element("value")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): MetaItem<*> {
|
||||||
|
val isNode = decoder.decodeBoolean()
|
||||||
|
return if (isNode) {
|
||||||
|
MetaItem.NodeItem(decoder.decode(MetaSerializer))
|
||||||
|
} else {
|
||||||
|
MetaItem.ValueItem(decoder.decode(ValueSerializer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, obj: MetaItem<*>) {
|
||||||
|
encoder.encodeBoolean(obj is MetaItem.NodeItem)
|
||||||
|
when (obj) {
|
||||||
|
is MetaItem.NodeItem -> MetaSerializer.serialize(encoder, obj.node)
|
||||||
|
is MetaItem.ValueItem -> ValueSerializer.serialize(encoder, obj.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DeserializedMeta(override val items: Map<NameToken, MetaItem<*>>) : MetaBase()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialized for meta
|
||||||
|
*/
|
||||||
|
@Serializer(Meta::class)
|
||||||
|
object MetaSerializer : KSerializer<Meta> {
|
||||||
|
private val mapSerializer =
|
||||||
|
HashMapSerializer(StringSerializer, MetaItemSerializer)
|
||||||
|
|
||||||
|
override val descriptor: SerialDescriptor =
|
||||||
|
NamedMapClassDescriptor("Meta", StringSerializer.descriptor, MetaItemSerializer.descriptor)
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): Meta {
|
||||||
|
return if (decoder is JsonInput) {
|
||||||
|
JsonObjectSerializer.deserialize(decoder).toMeta()
|
||||||
|
} else {
|
||||||
|
DeserializedMeta(mapSerializer.deserialize(decoder).mapKeys { NameToken(it.key) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, obj: Meta) {
|
||||||
|
if (encoder is JsonOutput) {
|
||||||
|
JsonObjectSerializer.serialize(encoder, obj.toJson())
|
||||||
|
} else {
|
||||||
|
mapSerializer.serialize(encoder, obj.items.mapKeys { it.key.toString() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializer(Config::class)
|
||||||
|
object ConfigSerializer : KSerializer<Config> {
|
||||||
|
override val descriptor: SerialDescriptor = MetaSerializer.descriptor
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): Config {
|
||||||
|
return MetaSerializer.deserialize(decoder).toConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, obj: Config) {
|
||||||
|
MetaSerializer.serialize(encoder, obj)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package hep.dataforge.io.serialization
|
||||||
|
|
||||||
|
import hep.dataforge.names.Name
|
||||||
|
import hep.dataforge.names.NameToken
|
||||||
|
import hep.dataforge.names.toName
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
import kotlinx.serialization.internal.StringDescriptor
|
||||||
|
|
||||||
|
@Serializer(Name::class)
|
||||||
|
object NameSerializer : KSerializer<Name> {
|
||||||
|
override val descriptor: SerialDescriptor = StringDescriptor.withName("Name")
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): Name {
|
||||||
|
return decoder.decodeString().toName()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, obj: Name) {
|
||||||
|
encoder.encodeString(obj.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializer(NameToken::class)
|
||||||
|
object NameTokenSerializer : KSerializer<NameToken> {
|
||||||
|
override val descriptor: SerialDescriptor = StringDescriptor.withName("NameToken")
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): NameToken {
|
||||||
|
return decoder.decodeString().toName().first()!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, obj: NameToken) {
|
||||||
|
encoder.encodeString(obj.toString())
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package hep.dataforge.io.serialization
|
||||||
|
|
||||||
|
import kotlinx.serialization.CompositeDecoder
|
||||||
|
import kotlinx.serialization.Decoder
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.SerialDescriptor
|
||||||
|
import kotlinx.serialization.internal.SerialClassDescImpl
|
||||||
|
|
||||||
|
inline class SerialDescriptorBuilder(private val impl: SerialClassDescImpl) {
|
||||||
|
fun element(name: String, isOptional: Boolean = false) = impl.addElement(name, isOptional)
|
||||||
|
|
||||||
|
fun annotation(a: Annotation) = impl.pushAnnotation(a)
|
||||||
|
|
||||||
|
fun classAnnotation(a: Annotation) = impl.pushClassAnnotation(a)
|
||||||
|
|
||||||
|
fun descriptor(name: String, block: SerialDescriptorBuilder.() -> Unit) = impl.pushDescriptor(
|
||||||
|
SerialDescriptorBuilder(SerialClassDescImpl(name)).apply(block).build()
|
||||||
|
)
|
||||||
|
|
||||||
|
fun build(): SerialDescriptor = impl
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun KSerializer<*>.descriptor(name: String, block: SerialDescriptorBuilder.() -> Unit): SerialDescriptor =
|
||||||
|
SerialDescriptorBuilder(SerialClassDescImpl(name)).apply(block).build()
|
||||||
|
|
||||||
|
fun Decoder.decodeStructure(
|
||||||
|
desc: SerialDescriptor,
|
||||||
|
vararg typeParams: KSerializer<*> = emptyArray(),
|
||||||
|
block: CompositeDecoder.() -> Unit
|
||||||
|
) {
|
||||||
|
beginStructure(desc, *typeParams).apply(block).endStructure(desc)
|
||||||
|
}
|
@ -4,13 +4,11 @@ import hep.dataforge.meta.*
|
|||||||
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.Ignore
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class MetaFormatTest {
|
class MetaFormatTest {
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
|
||||||
fun testBinaryMetaFormat() {
|
fun testBinaryMetaFormat() {
|
||||||
val meta = buildMeta {
|
val meta = buildMeta {
|
||||||
"a" to 22
|
"a" to 22
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
package hep.dataforge.io
|
package hep.dataforge.io
|
||||||
|
|
||||||
|
import hep.dataforge.io.serialization.NameSerializer
|
||||||
import hep.dataforge.meta.buildMeta
|
import hep.dataforge.meta.buildMeta
|
||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.toName
|
||||||
|
import kotlinx.io.charsets.Charsets
|
||||||
|
import kotlinx.io.core.String
|
||||||
|
import kotlinx.serialization.cbor.Cbor
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -23,6 +27,23 @@ class MetaSerializerTest {
|
|||||||
assertEquals(restored, meta)
|
assertEquals(restored, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCborSerialization() {
|
||||||
|
val meta = buildMeta {
|
||||||
|
"a" to 22
|
||||||
|
"node" to {
|
||||||
|
"b" to "DDD"
|
||||||
|
"c" to 11.1
|
||||||
|
"array" to doubleArrayOf(1.0, 2.0, 3.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val bytes = Cbor.dump(MetaSerializer, meta)
|
||||||
|
println(String(bytes, charset = Charsets.ISO_8859_1))
|
||||||
|
val restored = Cbor.load(MetaSerializer, bytes)
|
||||||
|
assertEquals(restored, meta)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNameSerialization() {
|
fun testNameSerialization() {
|
||||||
val name = "a.b.c".toName()
|
val name = "a.b.c".toName()
|
||||||
|
@ -17,7 +17,6 @@ internal class InputStreamAsInput(
|
|||||||
|
|
||||||
|
|
||||||
override fun fill(): IoBuffer? {
|
override fun fill(): IoBuffer? {
|
||||||
|
|
||||||
val packet = stream.readPacketAtMost(4096)
|
val packet = stream.readPacketAtMost(4096)
|
||||||
return pool.borrow().apply {
|
return pool.borrow().apply {
|
||||||
resetForWrite(4096)
|
resetForWrite(4096)
|
||||||
|
@ -2,7 +2,6 @@ package hep.dataforge.io
|
|||||||
|
|
||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import kotlin.test.Ignore
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
@ -22,7 +21,6 @@ class FileEnvelopeTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
|
||||||
fun testFileWriteRead() {
|
fun testFileWriteRead() {
|
||||||
val tmpPath = Files.createTempFile("dataforge_test", ".df")
|
val tmpPath = Files.createTempFile("dataforge_test", ".df")
|
||||||
Global.io.writeEnvelopeFile(tmpPath,envelope)
|
Global.io.writeEnvelopeFile(tmpPath,envelope)
|
||||||
|
@ -45,7 +45,6 @@ class EnvelopeServerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun doEchoTest() {
|
fun doEchoTest() {
|
||||||
|
|
||||||
val request = Envelope.invoke {
|
val request = Envelope.invoke {
|
||||||
type = "test.echo"
|
type = "test.echo"
|
||||||
meta {
|
meta {
|
||||||
|
@ -12,7 +12,7 @@ pluginManagement {
|
|||||||
eachPlugin {
|
eachPlugin {
|
||||||
when (requested.id.id) {
|
when (requested.id.id) {
|
||||||
"kotlinx-atomicfu" -> useModule("org.jetbrains.kotlinx:atomicfu-gradle-plugin:${requested.version}")
|
"kotlinx-atomicfu" -> useModule("org.jetbrains.kotlinx:atomicfu-gradle-plugin:${requested.version}")
|
||||||
"scientifik.mpp", "scientifik.publish" -> useModule("scientifik:gradle-tools:${requested.version}")
|
"scientifik.mpp", "scientifik.jvm", "scientifik.publish" -> useModule("scientifik:gradle-tools:${requested.version}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -24,6 +24,7 @@ enableFeaturePreview("GRADLE_METADATA")
|
|||||||
include(
|
include(
|
||||||
":dataforge-meta",
|
":dataforge-meta",
|
||||||
":dataforge-io",
|
":dataforge-io",
|
||||||
|
":dataforge-io:dataforge-io-yaml",
|
||||||
":dataforge-context",
|
":dataforge-context",
|
||||||
":dataforge-data",
|
":dataforge-data",
|
||||||
":dataforge-output",
|
":dataforge-output",
|
||||||
|
Loading…
Reference in New Issue
Block a user