Meta and io fixes
This commit is contained in:
parent
da4a9ebe9d
commit
efddfa8e91
@ -1,19 +1,14 @@
|
||||
plugins {
|
||||
id("scientifik.mpp") apply false
|
||||
id("scientifik.publish") apply false
|
||||
id("scientifik.mpp") version "0.1.4-dev" apply false
|
||||
id("scientifik.publish") version "0.1.4-dev" apply false
|
||||
}
|
||||
|
||||
val dataforgeVersion by extra("0.1.3-dev-9")
|
||||
val dataforgeVersion by extra("0.1.3-dev-10")
|
||||
|
||||
val bintrayRepo by extra("dataforge")
|
||||
val vcs by extra("https://github.com/mipt-npm/dataforge-core")
|
||||
val githubProject by extra("dataforge-core")
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven("https://kotlin.bintray.com/kotlinx")
|
||||
}
|
||||
|
||||
group = "hep.dataforge"
|
||||
version = dataforgeVersion
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ object Global : Context("GLOBAL", null) {
|
||||
return contextRegistry[name]
|
||||
}
|
||||
|
||||
fun context(name: String, parent: Context = this, block: ContextBuilder.() -> Unit): Context =
|
||||
fun context(name: String, parent: Context = this, block: ContextBuilder.() -> Unit = {}): Context =
|
||||
ContextBuilder(name, parent).apply(block).build()
|
||||
|
||||
}
|
||||
|
@ -2,56 +2,25 @@ plugins {
|
||||
id("scientifik.mpp")
|
||||
}
|
||||
|
||||
description = "IO for meta"
|
||||
description = "IO module"
|
||||
|
||||
scientifik{
|
||||
serialization = true
|
||||
io = true
|
||||
}
|
||||
|
||||
val ioVersion: String = Scientifik.ioVersion
|
||||
val serializationVersion: String = Scientifik.serializationVersion
|
||||
|
||||
kotlin {
|
||||
jvm()
|
||||
js()
|
||||
sourceSets {
|
||||
val commonMain by getting{
|
||||
dependencies {
|
||||
api(project(":dataforge-meta"))
|
||||
//implementation 'org.jetbrains.kotlin:kotlin-reflect'
|
||||
api("org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serializationVersion")
|
||||
api("org.jetbrains.kotlinx:kotlinx-io:$ioVersion")
|
||||
}
|
||||
}
|
||||
val commonTest by getting {
|
||||
dependencies {
|
||||
implementation("org.jetbrains.kotlin:kotlin-test-common")
|
||||
implementation("org.jetbrains.kotlin:kotlin-test-annotations-common")
|
||||
val jsMain by getting{
|
||||
dependencies{
|
||||
api(npm("text-encoding"))
|
||||
}
|
||||
}
|
||||
val jvmMain by getting {
|
||||
dependencies {
|
||||
api("org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serializationVersion")
|
||||
api("org.jetbrains.kotlinx:kotlinx-io-jvm:$ioVersion")
|
||||
}
|
||||
}
|
||||
val jvmTest by getting {
|
||||
dependencies {
|
||||
implementation("org.jetbrains.kotlin:kotlin-test")
|
||||
implementation("org.jetbrains.kotlin:kotlin-test-junit")
|
||||
}
|
||||
}
|
||||
val jsMain by getting {
|
||||
dependencies {
|
||||
api("org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$serializationVersion")
|
||||
api("org.jetbrains.kotlinx:kotlinx-io-js:$ioVersion")
|
||||
}
|
||||
}
|
||||
val jsTest by getting {
|
||||
dependencies {
|
||||
implementation("org.jetbrains.kotlin:kotlin-test-js")
|
||||
}
|
||||
}
|
||||
// iosMain {
|
||||
// }
|
||||
// iosTest {
|
||||
// }
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package hep.dataforge.io
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* A descriptor for specific type of functions
|
||||
*/
|
||||
interface FunctionSpec<T : Any, R : Any> {
|
||||
val inputType: KClass<T>
|
||||
val outputType: KClass<R>
|
||||
}
|
||||
|
||||
/**
|
||||
* A server that could produce asynchronous function values
|
||||
*/
|
||||
interface FunctionServer {
|
||||
/**
|
||||
* Call a function with given name and descriptor
|
||||
*/
|
||||
suspend fun <T : Any, R : Any, D : FunctionSpec<T, R>> call(name: String, descriptor: D, arg: T): R
|
||||
|
||||
/**
|
||||
* Resolve a function descriptor for given types
|
||||
*/
|
||||
fun <T : Any, R : Any> resolveType(inputType: KClass<out T>, outputType: KClass<out R>): FunctionSpec<T, R>
|
||||
|
||||
/**
|
||||
* Get a generic suspended function with given name and descriptor
|
||||
*/
|
||||
operator fun <T : Any, R : Any, D : FunctionSpec<T, R>> get(name: String, descriptor: D): (suspend (T) -> R) =
|
||||
{ call(name, descriptor, it) }
|
||||
}
|
||||
|
||||
suspend inline fun <reified T : Any, reified R : Any> FunctionServer.call(name: String, arg: T): R =
|
||||
call(name, resolveType(T::class, R::class), arg)
|
||||
|
||||
inline operator fun <reified T : Any, reified R : Any> FunctionServer.get(name: String): (suspend (T) -> R) =
|
||||
get(name, resolveType(T::class, R::class))
|
@ -13,14 +13,21 @@ interface MetaFormat : IOFormat<Meta> {
|
||||
val key: Short
|
||||
}
|
||||
|
||||
fun Meta.asString(format: MetaFormat = JsonMetaFormat): String {
|
||||
return buildPacket {
|
||||
format.run { writeObject(this@asString) }
|
||||
}.readText()
|
||||
fun Meta.toString(format: MetaFormat = JsonMetaFormat): String = buildPacket {
|
||||
format.run { writeObject(this@toString) }
|
||||
}.readText()
|
||||
|
||||
fun Meta.toBytes(format: MetaFormat = JsonMetaFormat): ByteReadPacket = buildPacket {
|
||||
format.run { writeObject(this@toBytes) }
|
||||
}
|
||||
|
||||
|
||||
fun MetaFormat.parse(str: String): Meta {
|
||||
return ByteReadPacket(str.toByteArray()).readObject()
|
||||
}
|
||||
|
||||
fun MetaFormat.fromBytes(packet: ByteReadPacket): Meta {
|
||||
return packet.readObject()
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package hep.dataforge.io
|
||||
|
||||
import hep.dataforge.meta.buildMeta
|
||||
import hep.dataforge.meta.get
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@ -12,10 +13,11 @@ class MetaFormatTest {
|
||||
"node" to {
|
||||
"b" to "DDD"
|
||||
"c" to 11.1
|
||||
"array" to doubleArrayOf(1.0, 2.0, 3.0)
|
||||
}
|
||||
}
|
||||
val string = meta.asString(BinaryMetaFormat)
|
||||
val result = BinaryMetaFormat.parse(string)
|
||||
val bytes = meta.toBytes(BinaryMetaFormat)
|
||||
val result = BinaryMetaFormat.fromBytes(bytes)
|
||||
assertEquals(meta, result)
|
||||
}
|
||||
|
||||
@ -26,11 +28,16 @@ class MetaFormatTest {
|
||||
"node" to {
|
||||
"b" to "DDD"
|
||||
"c" to 11.1
|
||||
"array" to doubleArrayOf(1.0,2.0,3.0)
|
||||
"array" to doubleArrayOf(1.0, 2.0, 3.0)
|
||||
}
|
||||
}
|
||||
val string = meta.asString(JsonMetaFormat)
|
||||
val string = meta.toString(JsonMetaFormat)
|
||||
val result = JsonMetaFormat.parse(string)
|
||||
|
||||
meta.items.keys.forEach {
|
||||
if (meta[it] != result[it]) error("${meta[it]} != ${result[it]}")
|
||||
}
|
||||
|
||||
assertEquals(meta, result)
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
package hep.dataforge.meta
|
||||
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.NameToken
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.names.plus
|
||||
|
||||
//TODO add validator to configuration
|
||||
|
||||
@ -10,6 +12,43 @@ import hep.dataforge.names.asName
|
||||
*/
|
||||
class Config : AbstractMutableMeta<Config>() {
|
||||
|
||||
private val listeners = HashSet<MetaListener>()
|
||||
|
||||
private fun itemChanged(name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) {
|
||||
listeners.forEach { it.action(name, oldItem, newItem) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Add change listener to this meta. Owner is declared to be able to remove listeners later. Listener without owner could not be removed
|
||||
*/
|
||||
fun onChange(owner: Any?, action: (Name, MetaItem<*>?, MetaItem<*>?) -> Unit) {
|
||||
listeners.add(MetaListener(owner, action))
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all listeners belonging to given owner
|
||||
*/
|
||||
fun removeListener(owner: Any?) {
|
||||
listeners.removeAll { it.owner === owner }
|
||||
}
|
||||
|
||||
override fun replaceItem(key: NameToken, oldItem: MetaItem<Config>?, newItem: MetaItem<Config>?) {
|
||||
if (newItem == null) {
|
||||
_items.remove(key)
|
||||
if(oldItem!= null && oldItem is MetaItem.NodeItem<Config>) {
|
||||
oldItem.node.removeListener(this)
|
||||
}
|
||||
} else {
|
||||
_items[key] = newItem
|
||||
if (newItem is MetaItem.NodeItem) {
|
||||
newItem.node.onChange(this) { name, oldChild, newChild ->
|
||||
itemChanged(key + name, oldChild, newChild)
|
||||
}
|
||||
}
|
||||
}
|
||||
itemChanged(key.asName(), oldItem, newItem)
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach configuration node instead of creating one
|
||||
*/
|
||||
|
@ -79,4 +79,14 @@ class Laminate(layers: List<Meta>) : Meta {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new [Laminate] adding given layer to the top
|
||||
*/
|
||||
fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
|
||||
|
||||
/**
|
||||
* Create a new [Laminate] adding given layer to the bottom
|
||||
*/
|
||||
fun Laminate.withBottom(meta: Meta): Laminate = Laminate(layers + meta)
|
||||
|
||||
//TODO add custom rules for Laminate merge
|
||||
|
@ -15,8 +15,16 @@ import hep.dataforge.values.boolean
|
||||
* * a [NodeItem] (node)
|
||||
*/
|
||||
sealed class MetaItem<out M : Meta> {
|
||||
data class ValueItem(val value: Value) : MetaItem<Nothing>()
|
||||
data class NodeItem<M : Meta>(val node: M) : MetaItem<M>()
|
||||
data class ValueItem(val value: Value) : MetaItem<Nothing>(){
|
||||
override fun toString(): String = value.string
|
||||
}
|
||||
data class NodeItem<M : Meta>(val node: M) : MetaItem<M>(){
|
||||
override fun toString(): String = node.toString()
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return this.node == (other as? NodeItem<*>).node
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,12 +182,14 @@ abstract class AbstractMetaNode<M : MetaNode<M>> : MetaNode<M> {
|
||||
if (this === other) return true
|
||||
if (other !is Meta) return false
|
||||
|
||||
return this.items == other.items
|
||||
return this.items == other.items//this.items.keys == other.items.keys && items.keys.all { this[it] == other[it] }
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return items.hashCode()
|
||||
}
|
||||
|
||||
override fun toString(): String = items.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -110,7 +110,7 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
|
||||
/**
|
||||
* Listens for changes in the source node and translates them into second node if transformation set contains a corresponding rule.
|
||||
*/
|
||||
fun <M : MutableMeta<M>> bind(source: MutableMeta<*>, target: M) {
|
||||
fun <M : MutableMeta<M>> bind(source: Config, target: M) {
|
||||
source.onChange(target) { name, _, newItem ->
|
||||
transformations.forEach { t ->
|
||||
if (t.matches(name, newItem)) {
|
||||
|
@ -12,8 +12,8 @@ internal data class MetaListener(
|
||||
interface MutableMeta<M : MutableMeta<M>> : MetaNode<M> {
|
||||
override val items: Map<NameToken, MetaItem<M>>
|
||||
operator fun set(name: Name, item: MetaItem<*>?)
|
||||
fun onChange(owner: Any? = null, action: (Name, MetaItem<*>?, MetaItem<*>?) -> Unit)
|
||||
fun removeListener(owner: Any? = null)
|
||||
// fun onChange(owner: Any? = null, action: (Name, MetaItem<*>?, MetaItem<*>?) -> Unit)
|
||||
// fun removeListener(owner: Any? = null)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -22,46 +22,20 @@ interface MutableMeta<M : MutableMeta<M>> : MetaNode<M> {
|
||||
* Changes in Meta are not thread safe.
|
||||
*/
|
||||
abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(), MutableMeta<M> {
|
||||
private val listeners = HashSet<MetaListener>()
|
||||
|
||||
/**
|
||||
* Add change listener to this meta. Owner is declared to be able to remove listeners later. Listener without owner could not be removed
|
||||
*/
|
||||
override fun onChange(owner: Any?, action: (Name, MetaItem<*>?, MetaItem<*>?) -> Unit) {
|
||||
listeners.add(MetaListener(owner, action))
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all listeners belonging to given owner
|
||||
*/
|
||||
override fun removeListener(owner: Any?) {
|
||||
listeners.removeAll { it.owner === owner }
|
||||
}
|
||||
|
||||
private val _items: MutableMap<NameToken, MetaItem<M>> = HashMap()
|
||||
protected val _items: MutableMap<NameToken, MetaItem<M>> = HashMap()
|
||||
|
||||
override val items: Map<NameToken, MetaItem<M>>
|
||||
get() = _items
|
||||
|
||||
protected fun itemChanged(name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) {
|
||||
listeners.forEach { it.action(name, oldItem, newItem) }
|
||||
}
|
||||
//protected abstract fun itemChanged(name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?)
|
||||
|
||||
protected open fun replaceItem(key: NameToken, oldItem: MetaItem<M>?, newItem: MetaItem<M>?) {
|
||||
if (newItem == null) {
|
||||
_items.remove(key)
|
||||
if(oldItem!= null && oldItem is MetaItem.NodeItem<M>) {
|
||||
oldItem.node.removeListener(this)
|
||||
}
|
||||
} else {
|
||||
_items[key] = newItem
|
||||
if (newItem is MetaItem.NodeItem) {
|
||||
newItem.node.onChange(this) { name, oldChild, newChild ->
|
||||
itemChanged(key + name, oldChild, newChild)
|
||||
}
|
||||
}
|
||||
}
|
||||
itemChanged(key.asName(), oldItem, newItem)
|
||||
//itemChanged(key.asName(), oldItem, newItem)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -42,12 +42,12 @@ class Styled(val base: Meta, val style: Config = Config().empty()) : AbstractMut
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChange(owner: Any?, action: (Name, before: MetaItem<*>?, after: MetaItem<*>?) -> Unit) {
|
||||
fun onChange(owner: Any?, action: (Name, before: MetaItem<*>?, after: MetaItem<*>?) -> Unit) {
|
||||
//TODO test correct behavior
|
||||
style.onChange(owner) { name, before, after -> action(name, before ?: base[name], after ?: base[name]) }
|
||||
}
|
||||
|
||||
override fun removeListener(owner: Any?) {
|
||||
fun removeListener(owner: Any?) {
|
||||
style.removeListener(owner)
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,8 @@ interface Value {
|
||||
val list: List<Value>
|
||||
get() = listOf(this)
|
||||
|
||||
override fun equals(other: Any?): Boolean
|
||||
|
||||
companion object {
|
||||
const val TYPE = "value"
|
||||
|
||||
@ -82,6 +84,8 @@ object Null : Value {
|
||||
override val string: String get() = "@null"
|
||||
|
||||
override fun toString(): String = value.toString()
|
||||
|
||||
override fun equals(other: Any?): Boolean = other === Null
|
||||
}
|
||||
|
||||
/**
|
||||
@ -100,6 +104,9 @@ object True : Value {
|
||||
override val string: String get() = "true"
|
||||
|
||||
override fun toString(): String = value.toString()
|
||||
|
||||
override fun equals(other: Any?): Boolean = other === True
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,6 +119,8 @@ object False : Value {
|
||||
override val string: String get() = "false"
|
||||
|
||||
override fun toString(): String = True.value.toString()
|
||||
|
||||
override fun equals(other: Any?): Boolean = other === False
|
||||
}
|
||||
|
||||
val Value.boolean get() = this == True || this.list.firstOrNull() == True || (type == ValueType.STRING && string.toBoolean())
|
||||
|
@ -12,9 +12,11 @@ class LazyParsedValue(override val string: String) : Value {
|
||||
override val number: Number get() = parsedValue.number
|
||||
|
||||
override fun toString(): String = string
|
||||
|
||||
override fun equals(other: Any?): Boolean = other is Value && this.parsedValue == other
|
||||
}
|
||||
|
||||
fun String.lazyParseValue(): LazyParsedValue = LazyParsedValue(this)
|
||||
fun String.lazyParseValue(): LazyParsedValue = LazyParsedValue(this)
|
||||
|
||||
/**
|
||||
* A performance optimized version of list value for doubles
|
||||
|
@ -1,18 +1,18 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
gradlePluginPortal()
|
||||
maven("https://dl.bintray.com/kotlin/kotlin-eap")
|
||||
maven("https://dl.bintray.com/kotlin/kotlinx")
|
||||
maven("https://dl.bintray.com/mipt-npm/scientifik")
|
||||
maven("https://dl.bintray.com/mipt-npm/dev")
|
||||
}
|
||||
resolutionStrategy {
|
||||
eachPlugin {
|
||||
when (requested.id.id) {
|
||||
"kotlinx-atomicfu" -> useModule("org.jetbrains.kotlinx:atomicfu-gradle-plugin:${requested.version}")
|
||||
"kotlin-multiplatform" -> useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
|
||||
"kotlin2js" -> useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
|
||||
"org.jetbrains.kotlin.frontend" -> useModule("org.jetbrains.kotlin:kotlin-frontend-plugin:0.0.45")
|
||||
"scientifik.mpp", "scientifik.publish" -> useModule("scientifik:gradle-tools:0.1.0")
|
||||
"scientifik.mpp", "scientifik.publish" -> useModule("scientifik:gradle-tools:${requested.version}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user