MetaFormat service loader

This commit is contained in:
Alexander Nozik 2018-12-05 09:55:30 +03:00
parent 3d65a1b409
commit 013a1a935c
14 changed files with 170 additions and 142 deletions

View File

@ -1,7 +1,7 @@
buildscript {
ext.kotlin_version = '1.3.0'
ext.serialization_version = '0.9.0'
ext.kotlinx_io_version = '0.1.0-beta-1'
ext.kotlin_version = '1.3.10'
ext.serialization_version = '0.9.1'
ext.kotlinx_io_version = '0.1.1'
repositories {
jcenter()

View File

@ -1,5 +1,5 @@
plugins {
id 'kotlin-multiplatform'
id "org.jetbrains.kotlin.multiplatform"
}
repositories {

View File

@ -1,5 +1,5 @@
plugins {
id 'kotlin-multiplatform'
id "org.jetbrains.kotlin.multiplatform"
}
repositories {

View File

@ -1,5 +1,5 @@
plugins {
id 'kotlin-multiplatform'
id "org.jetbrains.kotlin.multiplatform"
}
repositories {

View File

@ -1,8 +1,10 @@
plugins {
id 'kotlin-multiplatform'
id 'kotlinx-serialization'
id "org.jetbrains.kotlin.multiplatform"
}
description = "IO for meta"
repositories {
jcenter()
}

View File

@ -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
}

View File

@ -11,9 +11,7 @@ import kotlinx.io.core.writeText
import kotlinx.serialization.json.*
object JSONMetaFormat : MetaFormat {
override val name: String = "json"
override val key: Short = 0x4a53//"JS"
object JsonMetaFormat : MetaFormat {
override fun write(meta: Meta, out: Output) {
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
}

View File

@ -1,21 +1,27 @@
package hep.dataforge.meta.io
import hep.dataforge.meta.*
import hep.dataforge.values.*
import hep.dataforge.meta.Meta
import kotlinx.io.core.*
/**
* A format for meta serialization
*/
interface MetaFormat {
val name: String
val key: Short
fun write(meta: Meta, out: Output)
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()
format.write(this,builder)
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")
}
}
}

View File

@ -28,8 +28,8 @@ class MetaFormatTest{
"c" to 11.1
}
}
val string = meta.asString(JSONMetaFormat)
val result = JSONMetaFormat.parse(string)
val string = meta.asString(JsonMetaFormat)
val result = JsonMetaFormat.parse(string)
assertEquals(meta,result)
}

View File

@ -0,0 +1,2 @@
hep.dataforge.meta.io.BinaryMetaFormatFactory
hep.dataforge.meta.io.JsonMetaFormatFactory

View File

@ -1,5 +1,5 @@
plugins {
id 'kotlin-multiplatform'
id "org.jetbrains.kotlin.multiplatform"
}
repositories {

View File

@ -1,5 +1,5 @@
plugins {
id 'kotlin-multiplatform'
id "org.jetbrains.kotlin.multiplatform"
}
repositories {

View File

@ -1,5 +1,5 @@
plugins {
id 'kotlin-multiplatform'
id "org.jetbrains.kotlin.multiplatform"
}
repositories {

View File

@ -10,7 +10,7 @@ pluginManagement {
if (requested.id.id == "kotlin-platform-js") {
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}")
}
}
@ -22,6 +22,7 @@ pluginManagement {
}
}
enableFeaturePreview('GRADLE_METADATA')
rootProject.name = 'dataforge-core'