MetaFormat service loader
This commit is contained in:
parent
3d65a1b409
commit
013a1a935c
@ -1,7 +1,7 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.0'
|
ext.kotlin_version = '1.3.10'
|
||||||
ext.serialization_version = '0.9.0'
|
ext.serialization_version = '0.9.1'
|
||||||
ext.kotlinx_io_version = '0.1.0-beta-1'
|
ext.kotlinx_io_version = '0.1.1'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'kotlin-multiplatform'
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'kotlin-multiplatform'
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'kotlin-multiplatform'
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'kotlin-multiplatform'
|
id 'kotlin-multiplatform'
|
||||||
id 'kotlinx-serialization'
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
description = "IO for meta"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,132 @@
|
|||||||
|
package hep.dataforge.meta.io
|
||||||
|
|
||||||
|
import hep.dataforge.meta.*
|
||||||
|
import hep.dataforge.values.*
|
||||||
|
import kotlinx.io.core.Input
|
||||||
|
import kotlinx.io.core.Output
|
||||||
|
import kotlinx.io.core.readText
|
||||||
|
import kotlinx.io.core.writeText
|
||||||
|
|
||||||
|
object BinaryMetaFormat : MetaFormat {
|
||||||
|
override fun write(meta: Meta, out: Output) {
|
||||||
|
out.writeMeta(meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(input: Input): Meta {
|
||||||
|
return (input.readMetaItem() as MetaItem.NodeItem).node
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Output.writeChar(char: Char) = writeByte(char.toByte())
|
||||||
|
|
||||||
|
private fun Output.writeString(str: String) {
|
||||||
|
writeInt(str.length)
|
||||||
|
writeText(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Output.writeValue(value: Value) {
|
||||||
|
if (value.isList()) {
|
||||||
|
writeChar('L')
|
||||||
|
writeInt(value.list.size)
|
||||||
|
value.list.forEach {
|
||||||
|
writeValue(it)
|
||||||
|
}
|
||||||
|
} else when (value.type) {
|
||||||
|
ValueType.NUMBER -> when (value.value) {
|
||||||
|
is Short -> {
|
||||||
|
writeChar('s')
|
||||||
|
writeShort(value.number.toShort())
|
||||||
|
}
|
||||||
|
is Int -> {
|
||||||
|
writeChar('i')
|
||||||
|
writeInt(value.number.toInt())
|
||||||
|
}
|
||||||
|
is Long -> {
|
||||||
|
writeChar('l')
|
||||||
|
writeLong(value.number.toLong())
|
||||||
|
}
|
||||||
|
is Float -> {
|
||||||
|
writeChar('f')
|
||||||
|
writeFloat(value.number.toFloat())
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
writeChar('d')
|
||||||
|
writeDouble(value.number.toDouble())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ValueType.STRING -> {
|
||||||
|
writeChar('S')
|
||||||
|
writeString(value.string)
|
||||||
|
}
|
||||||
|
ValueType.BOOLEAN -> {
|
||||||
|
if (value.boolean) {
|
||||||
|
writeChar('+')
|
||||||
|
} else {
|
||||||
|
writeChar('-')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ValueType.NULL -> {
|
||||||
|
writeChar('N')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Output.writeMeta(meta: Meta) {
|
||||||
|
writeChar('M')
|
||||||
|
writeInt(meta.items.size)
|
||||||
|
meta.items.forEach { (key, item) ->
|
||||||
|
writeString(key.toString())
|
||||||
|
when (item) {
|
||||||
|
is MetaItem.ValueItem -> {
|
||||||
|
writeValue(item.value)
|
||||||
|
}
|
||||||
|
is MetaItem.NodeItem -> {
|
||||||
|
writeMeta(item.node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Input.readString(): String {
|
||||||
|
val length = readInt()
|
||||||
|
return readText(max = length)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Input.readMetaItem(): MetaItem<MetaBuilder> {
|
||||||
|
val keyChar = readByte().toChar()
|
||||||
|
return when (keyChar) {
|
||||||
|
'S' -> MetaItem.ValueItem(StringValue(readString()))
|
||||||
|
'N' -> MetaItem.ValueItem(Null)
|
||||||
|
'+' -> MetaItem.ValueItem(True)
|
||||||
|
'-' -> MetaItem.ValueItem(True)
|
||||||
|
's' -> MetaItem.ValueItem(NumberValue(readShort()))
|
||||||
|
'i' -> MetaItem.ValueItem(NumberValue(readInt()))
|
||||||
|
'l' -> MetaItem.ValueItem(NumberValue(readInt()))
|
||||||
|
'f' -> MetaItem.ValueItem(NumberValue(readFloat()))
|
||||||
|
'd' -> MetaItem.ValueItem(NumberValue(readDouble()))
|
||||||
|
'L' -> {
|
||||||
|
val length = readInt()
|
||||||
|
val list = (1..length).map { (readMetaItem() as MetaItem.ValueItem).value }
|
||||||
|
MetaItem.ValueItem(Value.of(list))
|
||||||
|
}
|
||||||
|
'M' -> {
|
||||||
|
val length = readInt()
|
||||||
|
val meta = buildMeta {
|
||||||
|
(1..length).forEach { _ ->
|
||||||
|
val name = readString()
|
||||||
|
val item = readMetaItem()
|
||||||
|
setItem(name, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MetaItem.NodeItem(meta)
|
||||||
|
}
|
||||||
|
else -> error("Unknown serialization key character: $keyChar")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BinaryMetaFormatFactory: MetaFormatFactory{
|
||||||
|
override val name: String = "bin"
|
||||||
|
override val key: Short = 0x4249//BI
|
||||||
|
|
||||||
|
override fun build(): MetaFormat = BinaryMetaFormat
|
||||||
|
}
|
@ -11,9 +11,7 @@ import kotlinx.io.core.writeText
|
|||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
|
|
||||||
|
|
||||||
object JSONMetaFormat : MetaFormat {
|
object JsonMetaFormat : MetaFormat {
|
||||||
override val name: String = "json"
|
|
||||||
override val key: Short = 0x4a53//"JS"
|
|
||||||
|
|
||||||
override fun write(meta: Meta, out: Output) {
|
override fun write(meta: Meta, out: Output) {
|
||||||
val str = meta.toJson().toString()
|
val str = meta.toJson().toString()
|
||||||
@ -74,4 +72,11 @@ class JsonMeta(val json: JsonObject) : Meta {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class JsonMetaFormatFactory: MetaFormatFactory{
|
||||||
|
override val name: String = "json"
|
||||||
|
override val key: Short = 0x4a53//"JS"
|
||||||
|
|
||||||
|
override fun build() = JsonMetaFormat
|
||||||
}
|
}
|
@ -1,21 +1,27 @@
|
|||||||
package hep.dataforge.meta.io
|
package hep.dataforge.meta.io
|
||||||
|
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.values.*
|
|
||||||
import kotlinx.io.core.*
|
import kotlinx.io.core.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A format for meta serialization
|
* A format for meta serialization
|
||||||
*/
|
*/
|
||||||
interface MetaFormat {
|
interface MetaFormat {
|
||||||
val name: String
|
|
||||||
val key: Short
|
|
||||||
|
|
||||||
fun write(meta: Meta, out: Output)
|
fun write(meta: Meta, out: Output)
|
||||||
fun read(input: Input): Meta
|
fun read(input: Input): Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Meta.asString(format: MetaFormat = JSONMetaFormat): String{
|
/**
|
||||||
|
* ServiceLoader compatible factory
|
||||||
|
*/
|
||||||
|
interface MetaFormatFactory {
|
||||||
|
val name: String
|
||||||
|
val key: Short
|
||||||
|
|
||||||
|
fun build(): MetaFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Meta.asString(format: MetaFormat = JsonMetaFormat): String{
|
||||||
val builder = BytePacketBuilder()
|
val builder = BytePacketBuilder()
|
||||||
format.write(this,builder)
|
format.write(this,builder)
|
||||||
return builder.build().readText()
|
return builder.build().readText()
|
||||||
@ -26,123 +32,3 @@ fun MetaFormat.parse(str: String): Meta{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
object BinaryMetaFormat : MetaFormat {
|
|
||||||
override val name: String = "bin"
|
|
||||||
override val key: Short = 0x4249//BI
|
|
||||||
|
|
||||||
override fun write(meta: Meta, out: Output) {
|
|
||||||
out.writeMeta(meta)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun read(input: Input): Meta {
|
|
||||||
return (input.readMetaItem() as MetaItem.NodeItem).node
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Output.writeChar(char: Char) = writeByte(char.toByte())
|
|
||||||
|
|
||||||
private fun Output.writeString(str: String) {
|
|
||||||
writeInt(str.length)
|
|
||||||
writeText(str)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Output.writeValue(value: Value) {
|
|
||||||
if (value.isList()) {
|
|
||||||
writeChar('L')
|
|
||||||
writeInt(value.list.size)
|
|
||||||
value.list.forEach {
|
|
||||||
writeValue(it)
|
|
||||||
}
|
|
||||||
} else when (value.type) {
|
|
||||||
ValueType.NUMBER -> when (value.value) {
|
|
||||||
is Short -> {
|
|
||||||
writeChar('s')
|
|
||||||
writeShort(value.number.toShort())
|
|
||||||
}
|
|
||||||
is Int -> {
|
|
||||||
writeChar('i')
|
|
||||||
writeInt(value.number.toInt())
|
|
||||||
}
|
|
||||||
is Long -> {
|
|
||||||
writeChar('l')
|
|
||||||
writeLong(value.number.toLong())
|
|
||||||
}
|
|
||||||
is Float -> {
|
|
||||||
writeChar('f')
|
|
||||||
writeFloat(value.number.toFloat())
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
writeChar('d')
|
|
||||||
writeDouble(value.number.toDouble())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ValueType.STRING -> {
|
|
||||||
writeChar('S')
|
|
||||||
writeString(value.string)
|
|
||||||
}
|
|
||||||
ValueType.BOOLEAN -> {
|
|
||||||
if (value.boolean) {
|
|
||||||
writeChar('+')
|
|
||||||
} else {
|
|
||||||
writeChar('-')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ValueType.NULL -> {
|
|
||||||
writeChar('N')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Output.writeMeta(meta: Meta) {
|
|
||||||
writeChar('M')
|
|
||||||
writeInt(meta.items.size)
|
|
||||||
meta.items.forEach { (key, item) ->
|
|
||||||
writeString(key.toString())
|
|
||||||
when (item) {
|
|
||||||
is MetaItem.ValueItem -> {
|
|
||||||
writeValue(item.value)
|
|
||||||
}
|
|
||||||
is MetaItem.NodeItem -> {
|
|
||||||
writeMeta(item.node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Input.readString(): String {
|
|
||||||
val length = readInt()
|
|
||||||
return readText(max = length)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Input.readMetaItem(): MetaItem<MetaBuilder> {
|
|
||||||
val keyChar = readByte().toChar()
|
|
||||||
return when (keyChar) {
|
|
||||||
'S' -> MetaItem.ValueItem(StringValue(readString()))
|
|
||||||
'N' -> MetaItem.ValueItem(Null)
|
|
||||||
'+' -> MetaItem.ValueItem(True)
|
|
||||||
'-' -> MetaItem.ValueItem(True)
|
|
||||||
's' -> MetaItem.ValueItem(NumberValue(readShort()))
|
|
||||||
'i' -> MetaItem.ValueItem(NumberValue(readInt()))
|
|
||||||
'l' -> MetaItem.ValueItem(NumberValue(readInt()))
|
|
||||||
'f' -> MetaItem.ValueItem(NumberValue(readFloat()))
|
|
||||||
'd' -> MetaItem.ValueItem(NumberValue(readDouble()))
|
|
||||||
'L' -> {
|
|
||||||
val length = readInt()
|
|
||||||
val list = (1..length).map { (readMetaItem() as MetaItem.ValueItem).value }
|
|
||||||
MetaItem.ValueItem(Value.of(list))
|
|
||||||
}
|
|
||||||
'M' -> {
|
|
||||||
val length = readInt()
|
|
||||||
val meta = buildMeta {
|
|
||||||
(1..length).forEach { _ ->
|
|
||||||
val name = readString()
|
|
||||||
val item = readMetaItem()
|
|
||||||
setItem(name, item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MetaItem.NodeItem(meta)
|
|
||||||
}
|
|
||||||
else -> error("Unknown serialization key character: $keyChar")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@ class MetaFormatTest{
|
|||||||
"c" to 11.1
|
"c" to 11.1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val string = meta.asString(JSONMetaFormat)
|
val string = meta.asString(JsonMetaFormat)
|
||||||
val result = JSONMetaFormat.parse(string)
|
val result = JsonMetaFormat.parse(string)
|
||||||
assertEquals(meta,result)
|
assertEquals(meta,result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
hep.dataforge.meta.io.BinaryMetaFormatFactory
|
||||||
|
hep.dataforge.meta.io.JsonMetaFormatFactory
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'kotlin-multiplatform'
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'kotlin-multiplatform'
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'kotlin-multiplatform'
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
@ -10,7 +10,7 @@ pluginManagement {
|
|||||||
if (requested.id.id == "kotlin-platform-js") {
|
if (requested.id.id == "kotlin-platform-js") {
|
||||||
useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
|
useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
|
||||||
}
|
}
|
||||||
if (requested.id.id == "kotlin-multiplatform") {
|
if (requested.id.id == "org.jetbrains.kotlin.multiplatform") {
|
||||||
useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
|
useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -22,6 +22,7 @@ pluginManagement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enableFeaturePreview('GRADLE_METADATA')
|
||||||
|
|
||||||
rootProject.name = 'dataforge-core'
|
rootProject.name = 'dataforge-core'
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user