Compare commits

...

9 Commits

57 changed files with 1253 additions and 868 deletions

View File

@ -4,16 +4,22 @@
### Added ### Added
- Name index comparator - Name index comparator
- Specialized ByteArrayValue
### Changed ### Changed
- DataSink `branch` is replaced with `putAll` to avoid confusion with DataTree methods - DataSink `branch` is replaced with `putAll` to avoid confusion with DataTree methods
- Meta delegate now uses a specific class that has a descriptor
### Deprecated ### Deprecated
### Removed ### Removed
### Fixed ### Fixed
- `listOfScheme` and `listOfConvertable` delegates provides correct items order - `listOfScheme` and `listOfConvertable` delegates provides correct items order.
- Scheme meta setter works with proper sub-branch.
- NameToken.parse improper work with indices.
- Proper data handling for cache.
### Security ### Security

View File

@ -8,7 +8,7 @@ plugins {
allprojects { allprojects {
group = "space.kscience" group = "space.kscience"
version = "0.8.1-dev-1" version = "0.8.2-dev-1"
} }
subprojects { subprojects {
@ -30,7 +30,7 @@ ksciencePublish {
useApache2Licence() useApache2Licence()
useSPCTeam() useSPCTeam()
} }
repository("spc","https://maven.sciprog.center/kscience") repository("spc", "https://maven.sciprog.center/kscience")
sonatype("https://oss.sonatype.org") sonatype("https://oss.sonatype.org")
} }

View File

@ -265,8 +265,6 @@ public abstract interface annotation class space/kscience/dataforge/descriptors/
} }
public final class space/kscience/dataforge/descriptors/ReflectiveDescriptorsKt { public final class space/kscience/dataforge/descriptors/ReflectiveDescriptorsKt {
public static final fun forClass (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor$Companion;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;
public static synthetic fun forClass$default (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor$Companion;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;
} }
public final class space/kscience/dataforge/properties/MetaAsFlowKt { public final class space/kscience/dataforge/properties/MetaAsFlowKt {

View File

@ -10,11 +10,11 @@ import space.kscience.dataforge.meta.ValueType
import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.MetaDescriptorBuilder import space.kscience.dataforge.meta.descriptors.MetaDescriptorBuilder
import space.kscience.dataforge.meta.descriptors.node import space.kscience.dataforge.meta.descriptors.node
import space.kscience.dataforge.misc.DFExperimental
import java.net.URL import java.net.URL
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.full.isSubclassOf import kotlin.reflect.full.isSubclassOf
import kotlin.reflect.full.memberProperties import kotlin.reflect.full.memberProperties
import kotlin.reflect.typeOf
/** /**
@ -58,9 +58,9 @@ private fun MetaDescriptorBuilder.loadDescriptorFromResource(resource: Descripto
} }
} }
@DFExperimental
public fun <T : Any> MetaDescriptor.Companion.forClass( public fun MetaDescriptor.Companion.forClass(
kClass: KClass<T>, kClass: KClass<out Any>,
mod: MetaDescriptorBuilder.() -> Unit = {}, mod: MetaDescriptorBuilder.() -> Unit = {},
): MetaDescriptor = MetaDescriptor { ): MetaDescriptor = MetaDescriptor {
when { when {
@ -79,7 +79,7 @@ public fun <T : Any> MetaDescriptor.Companion.forClass(
is DescriptorUrl -> loadDescriptorFromUrl(URL(it.url)) is DescriptorUrl -> loadDescriptorFromUrl(URL(it.url))
} }
} }
kClass.memberProperties.forEach { property -> kClass.memberProperties.forEach { property->
var flag = false var flag = false
@ -88,6 +88,12 @@ public fun <T : Any> MetaDescriptor.Companion.forClass(
(property.returnType.classifier as? KClass<*>)?.let { (property.returnType.classifier as? KClass<*>)?.let {
from(forClass(it)) from(forClass(it))
} }
//
// (property.getDelegate(Unit) as? MetaDelegate<*>)?.descriptor?.let {
// from(it)
// flag = true
// }
property.annotations.forEach { property.annotations.forEach {
when (it) { when (it) {
is Description -> { is Description -> {
@ -119,6 +125,6 @@ public fun <T : Any> MetaDescriptor.Companion.forClass(
mod() mod()
} }
@Suppress("UNCHECKED_CAST") @DFExperimental
public inline fun <reified T : Scheme> SchemeSpec<T>.autoDescriptor( noinline mod: MetaDescriptorBuilder.() -> Unit = {}): MetaDescriptor = public inline fun <reified T : Scheme> SchemeSpec<T>.autoDescriptor(noinline mod: MetaDescriptorBuilder.() -> Unit = {}): MetaDescriptor =
MetaDescriptor.forClass(typeOf<T>().classifier as KClass<T>, mod) MetaDescriptor.forClass(T::class, mod)

View File

@ -1,3 +1,5 @@
@file:OptIn(DFExperimental::class)
package space.kscience.dataforge.descriptors package space.kscience.dataforge.descriptors
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
@ -8,8 +10,9 @@ import space.kscience.dataforge.meta.SchemeSpec
import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.int import space.kscience.dataforge.meta.int
import space.kscience.dataforge.meta.string import space.kscience.dataforge.meta.string
import space.kscience.dataforge.misc.DFExperimental
private class TestScheme: Scheme(){ private class TestScheme : Scheme() {
@Description("A") @Description("A")
val a by string() val a by string()
@ -17,15 +20,17 @@ private class TestScheme: Scheme(){
@Description("B") @Description("B")
val b by int() val b by int()
companion object: SchemeSpec<TestScheme>(::TestScheme){ val c by int()
companion object : SchemeSpec<TestScheme>(::TestScheme) {
override val descriptor: MetaDescriptor = autoDescriptor() override val descriptor: MetaDescriptor = autoDescriptor()
} }
} }
class TestAutoDescriptors { class TestAutoDescriptors {
@Test @Test
fun autoDescriptor(){ fun autoDescriptor() {
val autoDescriptor = MetaDescriptor.forClass(TestScheme::class) val autoDescriptor = MetaDescriptor.forClass(TestScheme::class)
println(Json{prettyPrint = true}.encodeToString(autoDescriptor)) println(Json { prettyPrint = true }.encodeToString(autoDescriptor))
} }
} }

View File

@ -1,11 +1,14 @@
package space.kscience.dataforge.actions package space.kscience.dataforge.actions
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import space.kscience.dataforge.data.DataSink
import space.kscience.dataforge.data.* import space.kscience.dataforge.data.DataTree
import space.kscience.dataforge.data.DataUpdate
import space.kscience.dataforge.data.launchUpdate
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.misc.UnsafeKType
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.startsWith import space.kscience.dataforge.names.startsWith
import kotlin.reflect.KType import kotlin.reflect.KType
@ -29,7 +32,7 @@ public abstract class AbstractAction<T, R>(
* Generate initial content of the output * Generate initial content of the output
*/ */
protected abstract fun DataSink<R>.generate( protected abstract fun DataSink<R>.generate(
data: DataTree<T>, source: DataTree<T>,
meta: Meta, meta: Meta,
) )
@ -40,35 +43,28 @@ public abstract class AbstractAction<T, R>(
* @param meta the metadata used for the whole data tree * @param meta the metadata used for the whole data tree
* @param updatedData an updated item * @param updatedData an updated item
*/ */
protected open fun DataSink<R>.update( protected open suspend fun DataSink<R>.update(
source: DataTree<T>, source: DataTree<T>,
meta: Meta, meta: Meta,
updatedData: NamedData<T>, updatedData: DataUpdate<T>,
) { ) {
//by default regenerate the whole data set //by default regenerate the whole data set
generate(source, meta) generate(source, meta)
} }
@OptIn(DFInternal::class) @OptIn(UnsafeKType::class)
override fun execute( override fun execute(
dataSet: DataTree<T>, source: DataTree<T>,
meta: Meta, meta: Meta,
): DataTree<R> = if (dataSet.isObservable()) { updatesScope: CoroutineScope
MutableDataTree<R>(outputType, dataSet.updatesScope).apply { ): DataTree<R> = DataTree(outputType) {
generate(dataSet, meta) generate(source, meta)
dataSet.updates().onEach { //propagate updates
update(dataSet, meta, it) launchUpdate(updatesScope) {
}.launchIn(updatesScope) source.updates.onEach { update ->
update(source, meta, update)
//close updates when the source is closed }.collect()
updatesScope.launch {
dataSet.awaitClose()
close()
}
}
} else {
DataTree(outputType) {
generate(dataSet, meta)
} }
} }
} }

View File

@ -1,5 +1,8 @@
package space.kscience.dataforge.actions package space.kscience.dataforge.actions
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import space.kscience.dataforge.data.DataTree import space.kscience.dataforge.data.DataTree
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
@ -13,7 +16,7 @@ public fun interface Action<T, R> {
* Transform the data in the node, producing a new node. By default, it is assumed that all calculations are lazy * Transform the data in the node, producing a new node. By default, it is assumed that all calculations are lazy
* so not actual computation is started at this moment. * so not actual computation is started at this moment.
*/ */
public fun execute(dataSet: DataTree<T>, meta: Meta): DataTree<R> public fun execute(source: DataTree<T>, meta: Meta, updatesScope: CoroutineScope): DataTree<R>
public companion object public companion object
} }
@ -21,23 +24,27 @@ public fun interface Action<T, R> {
/** /**
* A convenience method to transform data using given [action] * A convenience method to transform data using given [action]
*/ */
@OptIn(DelicateCoroutinesApi::class)
public fun <T, R> DataTree<T>.transform( public fun <T, R> DataTree<T>.transform(
action: Action<T, R>, action: Action<T, R>,
meta: Meta = Meta.EMPTY, meta: Meta = Meta.EMPTY,
): DataTree<R> = action.execute(this, meta) updateScope: CoroutineScope = GlobalScope,
): DataTree<R> = action.execute(this, meta, updateScope)
/** /**
* Action composition. The result is terminal if one of its parts is terminal * Action composition. The result is terminal if one of its parts is terminal
*/ */
public infix fun <T, I, R> Action<T, I>.then(action: Action<I, R>): Action<T, R> = Action { dataSet, meta -> public infix fun <T, I, R> Action<T, I>.then(action: Action<I, R>): Action<T, R> = Action { dataSet, meta, scope ->
action.execute(this@then.execute(dataSet, meta), meta) action.execute(this@then.execute(dataSet, meta, scope), meta, scope)
} }
@DFExperimental @DFExperimental
@OptIn(DelicateCoroutinesApi::class)
public operator fun <T, R> Action<T, R>.invoke( public operator fun <T, R> Action<T, R>.invoke(
dataSet: DataTree<T>, dataSet: DataTree<T>,
meta: Meta = Meta.EMPTY, meta: Meta = Meta.EMPTY,
): DataTree<R> = execute(dataSet, meta) updateScope: CoroutineScope = GlobalScope,
): DataTree<R> = execute(dataSet, meta, updateScope)

View File

@ -6,7 +6,7 @@ import space.kscience.dataforge.meta.MutableMeta
import space.kscience.dataforge.meta.seal import space.kscience.dataforge.meta.seal
import space.kscience.dataforge.meta.toMutableMeta import space.kscience.dataforge.meta.toMutableMeta
import space.kscience.dataforge.misc.DFBuilder import space.kscience.dataforge.misc.DFBuilder
import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.misc.UnsafeKType
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import kotlin.reflect.KType import kotlin.reflect.KType
import kotlin.reflect.typeOf import kotlin.reflect.typeOf
@ -48,13 +48,18 @@ public class MapActionBuilder<T, R>(
public inline fun <reified R1 : R> result(noinline f: suspend ActionEnv.(T) -> R1): Unit = result(typeOf<R1>(), f) public inline fun <reified R1 : R> result(noinline f: suspend ActionEnv.(T) -> R1): Unit = result(typeOf<R1>(), f)
} }
@PublishedApi @UnsafeKType
internal class MapAction<T, R>( public class MapAction<T, R>(
outputType: KType, outputType: KType,
private val block: MapActionBuilder<T, R>.() -> Unit, private val block: MapActionBuilder<T, R>.() -> Unit,
) : AbstractAction<T, R>(outputType) { ) : AbstractAction<T, R>(outputType) {
private fun DataSink<R>.mapOne(name: Name, data: Data<T>, meta: Meta) { private fun DataSink<R>.mapOne(name: Name, data: Data<T>?, meta: Meta) {
//fast return for null data
if (data == null) {
put(name, null)
return
}
// Creating a new environment for action using **old** name, old meta and task meta // Creating a new environment for action using **old** name, old meta and task meta
val env = ActionEnv(name, data.meta, meta) val env = ActionEnv(name, data.meta, meta)
@ -73,7 +78,6 @@ internal class MapAction<T, R>(
//getting new meta //getting new meta
val newMeta = builder.meta.seal() val newMeta = builder.meta.seal()
@OptIn(DFInternal::class)
val newData = Data(builder.outputType, newMeta, dependencies = listOf(data)) { val newData = Data(builder.outputType, newMeta, dependencies = listOf(data)) {
builder.result(env, data.await()) builder.result(env, data.await())
} }
@ -81,12 +85,18 @@ internal class MapAction<T, R>(
put(newName, newData) put(newName, newData)
} }
override fun DataSink<R>.generate(data: DataTree<T>, meta: Meta) { override fun DataSink<R>.generate(source: DataTree<T>, meta: Meta) {
data.forEach { mapOne(it.name, it.data, meta) } source.forEach { mapOne(it.name, it.data, meta) }
} }
override fun DataSink<R>.update(source: DataTree<T>, meta: Meta, updatedData: NamedData<T>) {
mapOne(updatedData.name, updatedData.data, updatedData.meta)
override suspend fun DataSink<R>.update(
source: DataTree<T>,
meta: Meta,
updatedData: DataUpdate<T>,
) {
mapOne(updatedData.name, updatedData.data, meta)
} }
} }
@ -95,6 +105,7 @@ internal class MapAction<T, R>(
* A one-to-one mapping action * A one-to-one mapping action
*/ */
@OptIn(UnsafeKType::class)
public inline fun <T, reified R> Action.Companion.mapping( public inline fun <T, reified R> Action.Companion.mapping(
noinline builder: MapActionBuilder<T, R>.() -> Unit, noinline builder: MapActionBuilder<T, R>.() -> Unit,
): Action<T, R> = MapAction(typeOf<R>(), builder) ): Action<T, R> = MapAction(typeOf<R>(), builder)

View File

@ -4,7 +4,7 @@ import space.kscience.dataforge.data.*
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.meta.MutableMeta
import space.kscience.dataforge.misc.DFBuilder import space.kscience.dataforge.misc.DFBuilder
import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.misc.UnsafeKType
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.parseAsName import space.kscience.dataforge.names.parseAsName
import kotlin.reflect.KType import kotlin.reflect.KType
@ -84,8 +84,8 @@ internal class ReduceAction<T, R>(
) : AbstractAction<T, R>(outputType) { ) : AbstractAction<T, R>(outputType) {
//TODO optimize reduction. Currently, the whole action recalculates on push //TODO optimize reduction. Currently, the whole action recalculates on push
override fun DataSink<R>.generate(data: DataTree<T>, meta: Meta) { override fun DataSink<R>.generate(source: DataTree<T>, meta: Meta) {
ReduceGroupBuilder<T, R>(meta, outputType).apply(action).buildGroups(data).forEach { group -> ReduceGroupBuilder<T, R>(meta, outputType).apply(action).buildGroups(source).forEach { group ->
val dataFlow: Map<Name, Data<T>> = group.set.asSequence().fold(HashMap()) { acc, value -> val dataFlow: Map<Name, Data<T>> = group.set.asSequence().fold(HashMap()) { acc, value ->
acc.apply { acc.apply {
acc[value.name] = value.data acc[value.name] = value.data
@ -97,7 +97,7 @@ internal class ReduceAction<T, R>(
val groupMeta = group.meta val groupMeta = group.meta
val env = ActionEnv(groupName.parseAsName(), groupMeta, meta) val env = ActionEnv(groupName.parseAsName(), groupMeta, meta)
@OptIn(DFInternal::class) val res: Data<R> = dataFlow.reduceToData( @OptIn(UnsafeKType::class) val res: Data<R> = dataFlow.reduceToData(
group.outputType, group.outputType,
meta = groupMeta meta = groupMeta
) { group.result.invoke(env, it) } ) { group.result.invoke(env, it) }

View File

@ -48,10 +48,10 @@ internal class SplitAction<T, R>(
private val action: SplitBuilder<T, R>.() -> Unit, private val action: SplitBuilder<T, R>.() -> Unit,
) : AbstractAction<T, R>(outputType) { ) : AbstractAction<T, R>(outputType) {
private fun DataSink<R>.splitOne(name: Name, data: Data<T>, meta: Meta) { private fun DataSink<R>.splitOne(name: Name, data: Data<T>?, meta: Meta) {
val laminate = Laminate(data.meta, meta) val laminate = Laminate(data?.meta, meta)
val split = SplitBuilder<T, R>(name, data.meta).apply(action) val split = SplitBuilder<T, R>(name, data?.meta ?: Meta.EMPTY).apply(action)
// apply individual fragment rules to result // apply individual fragment rules to result
@ -63,6 +63,9 @@ internal class SplitAction<T, R>(
).apply(rule) ).apply(rule)
//data.map<R>(outputType, meta = env.meta) { env.result(it) }.named(fragmentName) //data.map<R>(outputType, meta = env.meta) { env.result(it) }.named(fragmentName)
if (data == null) {
put(fragmentName, null)
} else {
put( put(
fragmentName, fragmentName,
@Suppress("OPT_IN_USAGE") Data(outputType, meta = env.meta, dependencies = listOf(data)) { @Suppress("OPT_IN_USAGE") Data(outputType, meta = env.meta, dependencies = listOf(data)) {
@ -71,13 +74,18 @@ internal class SplitAction<T, R>(
) )
} }
} }
override fun DataSink<R>.generate(data: DataTree<T>, meta: Meta) {
data.forEach { splitOne(it.name, it.data, meta) }
} }
override fun DataSink<R>.update(source: DataTree<T>, meta: Meta, updatedData: NamedData<T>) { override fun DataSink<R>.generate(source: DataTree<T>, meta: Meta) {
splitOne(updatedData.name, updatedData.data, updatedData.meta) source.forEach { splitOne(it.name, it.data, meta) }
}
override suspend fun DataSink<R>.update(
source: DataTree<T>,
meta: Meta,
updatedData: DataUpdate<T>,
) {
splitOne(updatedData.name, updatedData.data, meta)
} }
} }

View File

@ -4,8 +4,8 @@ import kotlinx.coroutines.*
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.MetaRepr import space.kscience.dataforge.meta.MetaRepr
import space.kscience.dataforge.meta.isEmpty import space.kscience.dataforge.meta.isEmpty
import space.kscience.dataforge.misc.DFInternal
import space.kscience.dataforge.misc.DfType import space.kscience.dataforge.misc.DfType
import space.kscience.dataforge.misc.UnsafeKType
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.EmptyCoroutineContext
import kotlin.reflect.KType import kotlin.reflect.KType
@ -41,7 +41,7 @@ public interface Data<out T> : Goal<T>, MetaRepr {
*/ */
internal val TYPE_OF_NOTHING: KType = typeOf<Unit>() internal val TYPE_OF_NOTHING: KType = typeOf<Unit>()
public inline fun <reified T> static( public inline fun <reified T> wrapValue(
value: T, value: T,
meta: Meta = Meta.EMPTY, meta: Meta = Meta.EMPTY,
): Data<T> = StaticData(typeOf<T>(), value, meta) ): Data<T> = StaticData(typeOf<T>(), value, meta)
@ -50,10 +50,10 @@ public interface Data<out T> : Goal<T>, MetaRepr {
* An empty data containing only meta * An empty data containing only meta
*/ */
@OptIn(DelicateCoroutinesApi::class) @OptIn(DelicateCoroutinesApi::class)
public fun empty(meta: Meta): Data<Nothing> = object : Data<Nothing> { public fun buildEmpty(meta: Meta): Data<Nothing> = object : Data<Nothing> {
override val type: KType = TYPE_OF_NOTHING override val type: KType get() = TYPE_OF_NOTHING
override val meta: Meta = meta override val meta: Meta = meta
override val dependencies: Collection<Goal<*>> = emptyList() override val dependencies: Collection<Goal<*>> get() = emptyList()
override val deferred: Deferred<Nothing> override val deferred: Deferred<Nothing>
get() = GlobalScope.async(start = CoroutineStart.LAZY) { get() = GlobalScope.async(start = CoroutineStart.LAZY) {
error("The Data is empty and could not be computed") error("The Data is empty and could not be computed")
@ -62,6 +62,8 @@ public interface Data<out T> : Goal<T>, MetaRepr {
override fun async(coroutineScope: CoroutineScope): Deferred<Nothing> = deferred override fun async(coroutineScope: CoroutineScope): Deferred<Nothing> = deferred
override fun reset() {} override fun reset() {}
} }
public val EMPTY: Data<Nothing> = buildEmpty(Meta.EMPTY)
} }
} }
@ -87,7 +89,7 @@ public class StaticData<T>(
public inline fun <reified T> Data(value: T, meta: Meta = Meta.EMPTY): StaticData<T> = public inline fun <reified T> Data(value: T, meta: Meta = Meta.EMPTY): StaticData<T> =
StaticData(typeOf<T>(), value, meta) StaticData(typeOf<T>(), value, meta)
@DFInternal @UnsafeKType
public fun <T> Data( public fun <T> Data(
type: KType, type: KType,
meta: Meta = Meta.EMPTY, meta: Meta = Meta.EMPTY,
@ -96,7 +98,7 @@ public fun <T> Data(
block: suspend () -> T, block: suspend () -> T,
): Data<T> = LazyData(type, meta, context, dependencies, block) ): Data<T> = LazyData(type, meta, context, dependencies, block)
@OptIn(DFInternal::class) @OptIn(UnsafeKType::class)
public inline fun <reified T> Data( public inline fun <reified T> Data(
meta: Meta = Meta.EMPTY, meta: Meta = Meta.EMPTY,
context: CoroutineContext = EmptyCoroutineContext, context: CoroutineContext = EmptyCoroutineContext,

View File

@ -1,28 +1,30 @@
package space.kscience.dataforge.data package space.kscience.dataforge.data
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.NameToken
import space.kscience.dataforge.names.plus
import kotlin.reflect.KType import kotlin.reflect.KType
public fun interface DataFilter { public fun interface DataFilter {
public fun accepts(name: Name, meta: Meta, type: KType): Boolean public fun accepts(name: Name, meta: Meta?, type: KType): Boolean
public companion object { public companion object {
public val EMPTY: DataFilter = DataFilter { _, _, _ -> true } public val EMPTY: DataFilter = DataFilter { _, _, _ -> true }
} }
} }
public fun DataFilter.accepts(data: NamedData<*>): Boolean = accepts(data.name, data.meta, data.type)
public fun <T> Sequence<NamedData<T>>.filterData(predicate: DataFilter): Sequence<NamedData<T>> = filter { data -> public fun DataFilter.accepts(update: DataUpdate<*>): Boolean = accepts(update.name, update.data?.meta, update.type)
public fun <T, DU : DataUpdate<T>> Sequence<DU>.filterData(predicate: DataFilter): Sequence<DU> = filter { data ->
predicate.accepts(data) predicate.accepts(data)
} }
public fun <T> Flow<NamedData<T>>.filterData(predicate: DataFilter): Flow<NamedData<T>> = filter { data -> public fun <T, DU : DataUpdate<T>> Flow<DU>.filterData(predicate: DataFilter): Flow<DU> = filter { data ->
predicate.accepts(data) predicate.accepts(data)
} }
@ -41,7 +43,8 @@ public fun <T> DataSource<T>.filterData(
public fun <T> ObservableDataSource<T>.filterData( public fun <T> ObservableDataSource<T>.filterData(
predicate: DataFilter, predicate: DataFilter,
): ObservableDataSource<T> = object : ObservableDataSource<T> { ): ObservableDataSource<T> = object : ObservableDataSource<T> {
override fun updates(): Flow<NamedData<T>> = this@filterData.updates().filter { predicate.accepts(it) } override val updates: Flow<DataUpdate<T>>
get() = this@filterData.updates.filter { predicate.accepts(it) }
override val dataType: KType get() = this@filterData.dataType override val dataType: KType get() = this@filterData.dataType
@ -49,14 +52,32 @@ public fun <T> ObservableDataSource<T>.filterData(
this@filterData.read(name)?.takeIf { predicate.accepts(name, it.meta, it.type) } this@filterData.read(name)?.takeIf { predicate.accepts(name, it.meta, it.type) }
} }
public fun <T> GenericDataTree<T, *>.filterData( internal class FilteredDataTree<T>(
predicate: DataFilter, val source: DataTree<T>,
): DataTree<T> = asSequence().filterData(predicate).toTree(dataType) val filter: DataFilter,
val branch: Name,
override val dataType: KType = source.dataType,
) : DataTree<T> {
public fun <T> GenericObservableDataTree<T, *>.filterData( override val data: Data<T>?
scope: CoroutineScope, get() = source[branch].takeIf {
filter.accepts(Name.EMPTY, it?.meta, it?.type ?: dataType)
}
override val items: Map<NameToken, DataTree<T>>
get() = source.branch(branch)?.items
?.mapValues { FilteredDataTree(source, filter, branch + it.key) }
?.filter { !it.value.isEmpty() }
?: emptyMap()
override val updates: Flow<DataUpdate<T>>
get() = source.updates.filter { filter.accepts(it) }
}
public fun <T> DataTree<T>.filterData(
predicate: DataFilter, predicate: DataFilter,
): ObservableDataTree<T> = asSequence().filterData(predicate).toObservableTree(dataType, scope, updates().filterData(predicate)) ): DataTree<T> = FilteredDataTree(this, predicate, Name.EMPTY)
///** ///**

View File

@ -0,0 +1,159 @@
package space.kscience.dataforge.data
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.launch
import space.kscience.dataforge.misc.UnsafeKType
import space.kscience.dataforge.names.*
import kotlin.reflect.KType
import kotlin.reflect.typeOf
public interface DataSink<in T> {
/**
* Put data without notification
*/
public fun put(name: Name, data: Data<T>?)
/**
* Put data and propagate changes downstream
*/
public suspend fun update(name: Name, data: Data<T>?)
}
/**
* Launch continuous update using
*/
public fun <T> DataSink<T>.launchUpdate(
scope: CoroutineScope,
updater: suspend DataSink<T>.() -> Unit,
): Job = scope.launch {
object : DataSink<T> {
override fun put(name: Name, data: Data<T>?) {
launch {
this@launchUpdate.update(name, data)
}
}
override suspend fun update(name: Name, data: Data<T>?) {
this@launchUpdate.update(name, data)
}
}.updater()
}
/**
* A mutable version of [DataTree]
*/
public interface MutableDataTree<T> : DataTree<T>, DataSink<T> {
override var data: Data<T>?
override val items: Map<NameToken, MutableDataTree<T>>
public fun getOrCreateItem(token: NameToken): MutableDataTree<T>
public operator fun set(token: NameToken, data: Data<T>?)
override fun put(name: Name, data: Data<T>?): Unit = set(name, data)
}
public tailrec operator fun <T> MutableDataTree<T>.set(name: Name, data: Data<T>?): Unit {
when (name.length) {
0 -> this.data = data
1 -> set(name.first(), data)
else -> getOrCreateItem(name.first())[name.cutFirst()] = data
}
}
/**
* Provide a mutable subtree if it exists
*/
public tailrec fun <T> MutableDataTree<T>.branch(name: Name): MutableDataTree<T>? =
when (name.length) {
0 -> this
1 -> items[name.first()]
else -> items[name.first()]?.branch(name.cutFirst())
}
private class MutableDataTreeRoot<T>(
override val dataType: KType,
) : MutableDataTree<T> {
override val updates = MutableSharedFlow<DataUpdate<T>>(100, onBufferOverflow = BufferOverflow.DROP_LATEST)
inner class MutableDataTreeBranch(val branchName: Name) : MutableDataTree<T> {
override var data: Data<T>? = null
override val items = HashMap<NameToken, MutableDataTree<T>>()
override val updates: Flow<DataUpdate<T>> = this@MutableDataTreeRoot.updates.mapNotNull { update ->
update.name.removeFirstOrNull(branchName)?.let {
DataUpdate(update.data?.type ?: dataType, it, update.data)
}
}
override val dataType: KType get() = this@MutableDataTreeRoot.dataType
override fun getOrCreateItem(token: NameToken): MutableDataTree<T> =
items.getOrPut(token) { MutableDataTreeBranch(branchName + token) }
override fun set(token: NameToken, data: Data<T>?) {
val subTree = getOrCreateItem(token)
subTree.data = data
}
override suspend fun update(name: Name, data: Data<T>?) {
if (name.isEmpty()) {
this.data = data
this@MutableDataTreeRoot.updates.emit(DataUpdate(data?.type ?: dataType, branchName + name, data))
} else {
getOrCreateItem(name.first()).update(name.cutFirst(), data)
}
}
}
override var data: Data<T>? = null
override val items = HashMap<NameToken, MutableDataTree<T>>()
override fun getOrCreateItem(token: NameToken): MutableDataTree<T> = items.getOrPut(token) {
MutableDataTreeBranch(token.asName())
}
override fun set(token: NameToken, data: Data<T>?) {
val subTree = getOrCreateItem(token)
subTree.data = data
}
override suspend fun update(name: Name, data: Data<T>?) {
if (name.isEmpty()) {
this.data = data
updates.emit(DataUpdate(data?.type ?: dataType, name, data))
} else {
getOrCreateItem(name.first()).update(name.cutFirst(), data)
}
}
}
/**
* Create a new [MutableDataTree]
*/
@UnsafeKType
public fun <T> MutableDataTree(
type: KType,
): MutableDataTree<T> = MutableDataTreeRoot<T>(type)
/**
* Create and initialize a observable mutable data tree.
*/
@OptIn(UnsafeKType::class)
public inline fun <reified T> MutableDataTree(
generator: MutableDataTree<T>.() -> Unit = {},
): MutableDataTree<T> = MutableDataTree<T>(typeOf<T>()).apply { generator() }

View File

@ -1,9 +1,8 @@
package space.kscience.dataforge.data package space.kscience.dataforge.data
import kotlinx.coroutines.* import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.emptyFlow
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.misc.DFInternal
import space.kscience.dataforge.names.* import space.kscience.dataforge.names.*
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.reflect.KType import kotlin.reflect.KType
@ -33,46 +32,42 @@ public interface ObservableDataSource<out T> : DataSource<T> {
/** /**
* Flow updates made to the data * Flow updates made to the data
*/ */
public fun updates(): Flow<NamedData<T>> public val updates: Flow<DataUpdate<T>>
} }
/** /**
* A tree like structure for data holding * A tree like structure for data holding
*/ */
public interface GenericDataTree<out T, out TR : GenericDataTree<T, TR>> : DataSource<T> { public interface DataTree<out T> : ObservableDataSource<T> {
public val self: TR
public val data: Data<T>? public val data: Data<T>?
public val items: Map<NameToken, TR> public val items: Map<NameToken, DataTree<T>>
override fun read(name: Name): Data<T>? = when (name.length) { override fun read(name: Name): Data<T>? = when (name.length) {
0 -> data 0 -> data
else -> items[name.first()]?.read(name.cutFirst()) else -> items[name.first()]?.read(name.cutFirst())
} }
/**
* Flow updates made to the data
*/
override val updates: Flow<DataUpdate<T>>
public companion object { public companion object {
private object EmptyDataTree : GenericDataTree<Nothing, EmptyDataTree> { private object EmptyDataTree :
override val self: EmptyDataTree get() = this DataTree<Nothing> {
override val data: Data<Nothing>? = null override val data: Data<Nothing>? = null
override val items: Map<NameToken, EmptyDataTree> = emptyMap() override val items: Map<NameToken, EmptyDataTree> = emptyMap()
override val dataType: KType = typeOf<Unit>() override val dataType: KType = typeOf<Unit>()
override fun read(name: Name): Data<Nothing>? = null override fun read(name: Name): Data<Nothing>? = null
override val updates: Flow<DataUpdate<Nothing>> get() = emptyFlow()
} }
public val EMPTY: GenericDataTree<Nothing, *> = EmptyDataTree public val EMPTY: DataTree<Nothing> = EmptyDataTree
} }
} }
public typealias DataTree<T> = GenericDataTree<T, GenericDataTree<T, *>>
/**
* Return a single data in this tree. Throw error if it is not single.
*/
public fun <T> DataTree<T>.single(): NamedData<T> = asSequence().single()
/** /**
* An alias for easier access to tree values * An alias for easier access to tree values
*/ */
@ -93,238 +88,44 @@ public fun <T> DataTree<T>.asSequence(
} }
} }
/**
* Walk the data tree depth-first.
*
* @return a [Sequence] of pairs [Name]-[DataTree] for all nodes including the root one.
*/
public fun <T> DataTree<T>.walk(
namePrefix: Name = Name.EMPTY,
): Sequence<Pair<Name, DataTree<T>>> = sequence {
yield(namePrefix to this@walk)
items.forEach { (token, tree) ->
yieldAll(tree.walk(namePrefix + token))
}
}
public val DataTree<*>.meta: Meta? get() = data?.meta public val DataTree<*>.meta: Meta? get() = data?.meta
/** /**
* Provide subtree if it exists * Provide subtree if it exists
*/ */
public tailrec fun <T, TR : GenericDataTree<T, TR>> GenericDataTree<T, TR>.branch(name: Name): TR? = public tailrec fun <T> DataTree<T>.branch(name: Name): DataTree<T>? =
when (name.length) { when (name.length) {
0 -> self 0 -> this
1 -> items[name.first()] 1 -> items[name.first()]
else -> items[name.first()]?.branch(name.cutFirst()) else -> items[name.first()]?.branch(name.cutFirst())
} }
public fun <T, TR : GenericDataTree<T, TR>> GenericDataTree<T, TR>.branch(name: String): TR? = public fun <T> DataTree<T>.branch(name: String): DataTree<T>? =
branch(name.parseAsName()) branch(name.parseAsName())
public fun GenericDataTree<*, *>.isEmpty(): Boolean = data == null && items.isEmpty() public fun DataTree<*>.isEmpty(): Boolean = data == null && items.isEmpty()
@PublishedApi
internal class FlatDataTree<T>(
override val dataType: KType,
private val dataSet: Map<Name, Data<T>>,
private val prefix: Name,
) : GenericDataTree<T, FlatDataTree<T>> {
override val self: FlatDataTree<T> get() = this
override val data: Data<T>? get() = dataSet[prefix]
override val items: Map<NameToken, FlatDataTree<T>>
get() = dataSet.keys
.filter { it.startsWith(prefix) && it.length > prefix.length }
.map { it.tokens[prefix.length] }
.associateWith { FlatDataTree(dataType, dataSet, prefix + it) }
override fun read(name: Name): Data<T>? = dataSet[prefix + name]
}
/**
* Represent this flat data map as a [DataTree] without copying it
*/
public inline fun <reified T> Map<Name, Data<T>>.asTree(): DataTree<T> = FlatDataTree(typeOf<T>(), this, Name.EMPTY)
internal fun <T> Sequence<NamedData<T>>.toTree(type: KType): DataTree<T> =
FlatDataTree(type, associate { it.name to it.data }, Name.EMPTY)
/**
* Collect a sequence of [NamedData] to a [DataTree]
*/
public inline fun <reified T> Sequence<NamedData<T>>.toTree(): DataTree<T> =
FlatDataTree(typeOf<T>(), associate { it.name to it.data }, Name.EMPTY)
public interface GenericObservableDataTree<out T, out TR : GenericObservableDataTree<T, TR>> :
GenericDataTree<T, TR>, ObservableDataSource<T>, AutoCloseable {
/**
* A scope that is used to propagate updates. When this scope is closed, no new updates could arrive.
*/
public val updatesScope: CoroutineScope
/**
* Close this data tree updates channel
*/
override fun close() {
updatesScope.cancel()
}
}
public typealias ObservableDataTree<T> = GenericObservableDataTree<T, GenericObservableDataTree<T, *>>
/** /**
* Check if the [DataTree] is observable * Check if the [DataTree] is observable
*/ */
public fun <T> DataTree<T>.isObservable(): Boolean { public fun <T> DataSource<T>.isObservable(): Boolean {
contract { contract {
returns(true) implies (this@isObservable is GenericObservableDataTree<T, *>) returns(true) implies (this@isObservable is ObservableDataSource<T>)
} }
return this is GenericObservableDataTree<T, *> return this is ObservableDataSource<T>
} }
/**
* Wait for this data tree to stop spawning updates (updatesScope is closed).
* If this [DataTree] is not observable, return immediately.
*/
public suspend fun <T> DataTree<T>.awaitClose() {
if (isObservable()) {
updatesScope.coroutineContext[Job]?.join()
}
}
public fun <T> DataTree<T>.updates(): Flow<NamedData<T>> =
if (this is GenericObservableDataTree<T, *>) updates() else emptyFlow()
public fun interface DataSink<in T> {
public fun put(name: Name, data: Data<T>?)
}
@DFInternal
public class DataTreeBuilder<T>(private val type: KType) : DataSink<T> {
private val map = HashMap<Name, Data<T>>()
override fun put(name: Name, data: Data<T>?) {
if (data == null) {
map.remove(name)
} else {
map[name] = data
}
}
public fun build(): DataTree<T> = FlatDataTree(type, map, Name.EMPTY)
}
@DFInternal
public inline fun <T> DataTree(
dataType: KType,
generator: DataSink<T>.() -> Unit,
): DataTree<T> = DataTreeBuilder<T>(dataType).apply(generator).build()
/**
* Create and a data tree.
*/
@OptIn(DFInternal::class)
public inline fun <reified T> DataTree(
generator: DataSink<T>.() -> Unit,
): DataTree<T> = DataTreeBuilder<T>(typeOf<T>()).apply(generator).build()
/**
* A mutable version of [GenericDataTree]
*/
public interface MutableDataTree<T> : GenericObservableDataTree<T, MutableDataTree<T>>, DataSink<T> {
override var data: Data<T>?
override val items: Map<NameToken, MutableDataTree<T>>
public fun getOrCreateItem(token: NameToken): MutableDataTree<T>
public operator fun set(token: NameToken, data: Data<T>?)
override fun put(name: Name, data: Data<T>?): Unit = set(name, data)
}
public tailrec operator fun <T> MutableDataTree<T>.set(name: Name, data: Data<T>?): Unit {
when (name.length) {
0 -> this.data = data
1 -> set(name.first(), data)
else -> getOrCreateItem(name.first())[name.cutFirst()] = data
}
}
private class MutableDataTreeImpl<T>(
override val dataType: KType,
override val updatesScope: CoroutineScope,
) : MutableDataTree<T> {
private val updates = MutableSharedFlow<NamedData<T>>()
private val children = HashMap<NameToken, MutableDataTree<T>>()
override var data: Data<T>? = null
set(value) {
if (!updatesScope.isActive) error("Can't send updates to closed MutableDataTree")
field = value
if (value != null) {
updatesScope.launch {
updates.emit(value.named(Name.EMPTY))
}
}
}
override val items: Map<NameToken, MutableDataTree<T>> get() = children
override fun getOrCreateItem(token: NameToken): MutableDataTree<T> = children.getOrPut(token){
MutableDataTreeImpl(dataType, updatesScope)
}
override val self: MutableDataTree<T> get() = this
override fun set(token: NameToken, data: Data<T>?) {
if (!updatesScope.isActive) error("Can't send updates to closed MutableDataTree")
val subTree = getOrCreateItem(token)
subTree.updates().onEach {
updates.emit(it.named(token + it.name))
}.launchIn(updatesScope)
subTree.data = data
}
override fun updates(): Flow<NamedData<T>> = updates
}
/**
* Create a new [MutableDataTree]
*
* @param parentScope a [CoroutineScope] to control data propagation. By default uses [GlobalScope]
*/
@OptIn(DelicateCoroutinesApi::class)
public fun <T> MutableDataTree(
type: KType,
parentScope: CoroutineScope = GlobalScope,
): MutableDataTree<T> = MutableDataTreeImpl<T>(
type,
CoroutineScope(parentScope.coroutineContext + Job(parentScope.coroutineContext[Job]))
)
/**
* Create and initialize a observable mutable data tree.
*/
@OptIn(DelicateCoroutinesApi::class)
public inline fun <reified T> MutableDataTree(
parentScope: CoroutineScope = GlobalScope,
generator: MutableDataTree<T>.() -> Unit = {},
): MutableDataTree<T> = MutableDataTree<T>(typeOf<T>(), parentScope).apply { generator() }
//@DFInternal
//public fun <T> ObservableDataTree(
// type: KType,
// scope: CoroutineScope,
// generator: suspend MutableDataTree<T>.() -> Unit = {},
//): ObservableDataTree<T> = MutableDataTree<T>(type, scope.coroutineContext).apply(generator)
public inline fun <reified T> ObservableDataTree(
parentScope: CoroutineScope,
generator: MutableDataTree<T>.() -> Unit = {},
): ObservableDataTree<T> = MutableDataTree<T>(typeOf<T>(), parentScope).apply(generator)
/**
* Collect a [Sequence] into an observable tree with additional [updates]
*/
public fun <T> Sequence<NamedData<T>>.toObservableTree(
dataType: KType,
parentScope: CoroutineScope,
updates: Flow<NamedData<T>>,
): ObservableDataTree<T> = MutableDataTree<T>(dataType, parentScope).apply {
this.putAll(this@toObservableTree)
updates.onEach {
put(it.name, it.data)
}.launchIn(updatesScope)
}

View File

@ -17,7 +17,7 @@ package space.kscience.dataforge.data
import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.string import space.kscience.dataforge.meta.string
import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.misc.UnsafeKType
public interface GroupRule { public interface GroupRule {
public fun <T> gather(set: DataTree<T>): Map<String, DataTree<T>> public fun <T> gather(set: DataTree<T>): Map<String, DataTree<T>>
@ -31,7 +31,7 @@ public interface GroupRule {
* @param defaultTagValue * @param defaultTagValue
* @return * @return
*/ */
@OptIn(DFInternal::class) @OptIn(UnsafeKType::class)
public fun byMetaValue( public fun byMetaValue(
key: String, key: String,
defaultTagValue: String, defaultTagValue: String,
@ -40,15 +40,15 @@ public interface GroupRule {
override fun <T> gather( override fun <T> gather(
set: DataTree<T>, set: DataTree<T>,
): Map<String, DataTree<T>> { ): Map<String, DataTree<T>> {
val map = HashMap<String, DataTreeBuilder<T>>() val map = HashMap<String, MutableDataTree<T>>()
set.forEach { data -> set.forEach { data ->
val tagValue: String = data.meta[key]?.string ?: defaultTagValue val tagValue: String = data.meta[key]?.string ?: defaultTagValue
map.getOrPut(tagValue) { DataTreeBuilder(set.dataType) }.put(data.name, data.data) map.getOrPut(tagValue) { MutableDataTree(set.dataType) }.put(data.name, data.data)
} }
return map.mapValues { it.value.build() } return map
} }
} }
} }

View File

@ -20,4 +20,4 @@ public fun <T> Data<T>.withMeta(newMeta: Meta): Data<T> = if (this is MetaMaskDa
* Create a new [Data] with the same computation, but different meta. The meta is created by applying [block] to * Create a new [Data] with the same computation, but different meta. The meta is created by applying [block] to
* the existing data meta. * the existing data meta.
*/ */
public inline fun <T> Data<T>.mapMeta(block: MutableMeta.() -> Unit): Data<T> = withMeta(meta.copy(block)) public inline fun <T> Data<T>.withMeta(block: MutableMeta.() -> Unit): Data<T> = withMeta(meta.copy(block))

View File

@ -3,10 +3,30 @@ package space.kscience.dataforge.data
import space.kscience.dataforge.meta.isEmpty import space.kscience.dataforge.meta.isEmpty
import space.kscience.dataforge.misc.Named import space.kscience.dataforge.misc.Named
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import kotlin.reflect.KType
public interface NamedData<out T> : Named, Data<T> { /**
* An interface implementing a data update event.
*
* If [data] is null, then corresponding element should be removed.
*/
public interface DataUpdate<out T> : Named {
public val type: KType
override val name: Name override val name: Name
public val data: Data<T> public val data: Data<T>?
}
public fun <T> DataUpdate(type: KType, name: Name, data: Data<T>?): DataUpdate<T> = object : DataUpdate<T> {
override val type: KType = type
override val name: Name = name
override val data: Data<T>? = data
}
/**
* A data coupled to a name.
*/
public interface NamedData<out T> : DataUpdate<T>, Data<T> {
override val data: Data<T>
} }
public operator fun NamedData<*>.component1(): Name = name public operator fun NamedData<*>.component1(): Name = name
@ -33,3 +53,5 @@ public fun <T> Data<T>.named(name: Name): NamedData<T> = if (this is NamedData)
} else { } else {
NamedDataImpl(name, this) NamedDataImpl(name, this)
} }
public fun <T> NamedData(name: Name, data: Data<T>): NamedData<T> = data.named(name)

View File

@ -1,14 +1,12 @@
package space.kscience.dataforge.data package space.kscience.dataforge.data
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.meta.MutableMeta
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.*
import space.kscience.dataforge.names.asName
import space.kscience.dataforge.names.isEmpty
import space.kscience.dataforge.names.plus
public fun <T> DataSink<T>.put(value: NamedData<T>) { public fun <T> DataSink<T>.put(value: NamedData<T>) {
@ -22,31 +20,27 @@ public inline fun <T> DataSink<T>.putAll(
if (prefix.isEmpty()) { if (prefix.isEmpty()) {
apply(block) apply(block)
} else { } else {
val proxyDataSink = DataSink { nameWithoutPrefix, data -> val proxyDataSink = object :DataSink<T>{
this.put(prefix + nameWithoutPrefix, data) override fun put(name: Name, data: Data<T>?) {
this@putAll.put(prefix + name, data)
}
override suspend fun update(name: Name, data: Data<T>?) {
this@putAll.update(prefix + name, data)
}
} }
proxyDataSink.apply(block) proxyDataSink.apply(block)
} }
} }
@Deprecated("Use putAll", ReplaceWith("putAll(prefix, block)"))
public inline fun <T> DataSink<T>.branch(
prefix: Name,
block: DataSink<T>.() -> Unit,
): Unit = putAll(prefix, block)
public inline fun <T> DataSink<T>.putAll( public inline fun <T> DataSink<T>.putAll(
prefix: String, prefix: String,
block: DataSink<T>.() -> Unit, block: DataSink<T>.() -> Unit,
): Unit = putAll(prefix.asName(), block) ): Unit = putAll(prefix.asName(), block)
@Deprecated("Use putAll", ReplaceWith("putAll(prefix, block)"))
public inline fun <T> DataSink<T>.branch(
prefix: String,
block: DataSink<T>.() -> Unit,
): Unit = putAll(prefix, block)
public fun <T> DataSink<T>.put(name: String, value: Data<T>) { public fun <T> DataSink<T>.put(name: String, value: Data<T>) {
put(Name.parse(name), value) put(Name.parse(name), value)
@ -56,20 +50,15 @@ public fun <T> DataSink<T>.putAll(name: Name, tree: DataTree<T>) {
putAll(name) { putAll(tree.asSequence()) } putAll(name) { putAll(tree.asSequence()) }
} }
@Deprecated("Use putAll", ReplaceWith("putAll(name, tree)"))
public fun <T> DataSink<T>.branch(name: Name, tree: DataTree<T>): Unit = putAll(name, tree)
public fun <T> DataSink<T>.putAll(name: String, tree: DataTree<T>) { public fun <T> DataSink<T>.putAll(name: String, tree: DataTree<T>) {
putAll(Name.parse(name)) { putAll(tree.asSequence()) } putAll(Name.parse(name)) { putAll(tree.asSequence()) }
} }
@Deprecated("Use putAll", ReplaceWith("putAll(name, tree)"))
public fun <T> DataSink<T>.branch(name: String, tree: DataTree<T>): Unit = putAll(name, tree)
/** /**
* Produce lazy [Data] and emit it into the [MutableDataTree] * Produce lazy [Data] and emit it into the [MutableDataTree]
*/ */
public inline fun <reified T> DataSink<T>.put( public inline fun <reified T> DataSink<T>.putValue(
name: String, name: String,
meta: Meta = Meta.EMPTY, meta: Meta = Meta.EMPTY,
noinline producer: suspend () -> T, noinline producer: suspend () -> T,
@ -78,7 +67,7 @@ public inline fun <reified T> DataSink<T>.put(
put(name, data) put(name, data)
} }
public inline fun <reified T> DataSink<T>.put( public inline fun <reified T> DataSink<T>.putValue(
name: Name, name: Name,
meta: Meta = Meta.EMPTY, meta: Meta = Meta.EMPTY,
noinline producer: suspend () -> T, noinline producer: suspend () -> T,
@ -90,24 +79,35 @@ public inline fun <reified T> DataSink<T>.put(
/** /**
* Emit static data with the fixed value * Emit static data with the fixed value
*/ */
public inline fun <reified T> DataSink<T>.wrap( public inline fun <reified T> DataSink<T>.putValue(
name: String,
data: T,
meta: Meta = Meta.EMPTY,
): Unit = put(name, Data.static(data, meta))
public inline fun <reified T> DataSink<T>.wrap(
name: Name, name: Name,
data: T, value: T,
meta: Meta = Meta.EMPTY, meta: Meta = Meta.EMPTY,
): Unit = put(name, Data.static(data, meta)) ): Unit = put(name, Data.wrapValue(value, meta))
public inline fun <reified T> DataSink<T>.wrap( public inline fun <reified T> DataSink<T>.putValue(
name: String, name: String,
data: T, value: T,
mutableMeta: MutableMeta.() -> Unit, meta: Meta = Meta.EMPTY,
): Unit = put(Name.parse(name), Data.static(data, Meta(mutableMeta))) ): Unit = put(name, Data.wrapValue(value, meta))
public inline fun <reified T> DataSink<T>.putValue(
name: String,
value: T,
metaBuilder: MutableMeta.() -> Unit,
): Unit = put(Name.parse(name), Data.wrapValue(value, Meta(metaBuilder)))
public suspend inline fun <reified T> DataSink<T>.updateValue(
name: Name,
value: T,
meta: Meta = Meta.EMPTY,
): Unit = update(name, Data.wrapValue(value, meta))
public suspend inline fun <reified T> DataSink<T>.updateValue(
name: String,
value: T,
meta: Meta = Meta.EMPTY,
): Unit = update(name.parseAsName(), Data.wrapValue(value, meta))
public fun <T> DataSink<T>.putAll(sequence: Sequence<NamedData<T>>) { public fun <T> DataSink<T>.putAll(sequence: Sequence<NamedData<T>>) {
sequence.forEach { sequence.forEach {
@ -123,18 +123,12 @@ public fun <T> DataSink<T>.putAll(tree: DataTree<T>) {
* Copy given data set and mirror its changes to this [DataSink] in [this@setAndObserve]. Returns an update [Job] * Copy given data set and mirror its changes to this [DataSink] in [this@setAndObserve]. Returns an update [Job]
*/ */
public fun <T : Any> DataSink<T>.putAllAndWatch( public fun <T : Any> DataSink<T>.putAllAndWatch(
scope: CoroutineScope,
branchName: Name = Name.EMPTY, branchName: Name = Name.EMPTY,
dataSet: ObservableDataTree<T>, source: DataTree<T>,
): Job { ): Job {
putAll(branchName, dataSet) putAll(branchName, source)
return dataSet.updates().onEach { return source.updates.onEach {
put(branchName + it.name, it.data) update(branchName + it.name, it.data)
}.launchIn(dataSet.updatesScope) }.launchIn(scope)
} }
@Deprecated("Use putAllAndWatch", ReplaceWith("putAllAndWatch(name, dataSet)"))
public fun <T : Any> DataSink<T>.watchBranch(
name: Name,
dataSet: ObservableDataTree<T>,
): Job = putAllAndWatch(name, dataSet)

View File

@ -1,7 +1,7 @@
package space.kscience.dataforge.data package space.kscience.dataforge.data
import space.kscience.dataforge.meta.* import space.kscience.dataforge.meta.*
import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.misc.UnsafeKType
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.NameToken import space.kscience.dataforge.names.NameToken
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@ -68,7 +68,7 @@ internal fun Map<*, Data<*>>.joinMeta(): Meta = Meta {
} }
} }
@DFInternal @UnsafeKType
public fun <K, T, R> Map<K, Data<T>>.reduceToData( public fun <K, T, R> Map<K, Data<T>>.reduceToData(
outputType: KType, outputType: KType,
meta: Meta = joinMeta(), meta: Meta = joinMeta(),
@ -103,7 +103,7 @@ public inline fun <K, T, reified R> Map<K, Data<T>>.reduceToData(
//Iterable operations //Iterable operations
@DFInternal @UnsafeKType
public inline fun <T, R> Iterable<Data<T>>.reduceToData( public inline fun <T, R> Iterable<Data<T>>.reduceToData(
outputType: KType, outputType: KType,
meta: Meta = joinMeta(), meta: Meta = joinMeta(),
@ -118,7 +118,7 @@ public inline fun <T, R> Iterable<Data<T>>.reduceToData(
transformation(map { it.awaitWithMeta() }) transformation(map { it.awaitWithMeta() })
} }
@OptIn(DFInternal::class) @OptIn(UnsafeKType::class)
public inline fun <T, reified R> Iterable<Data<T>>.reduceToData( public inline fun <T, reified R> Iterable<Data<T>>.reduceToData(
meta: Meta = joinMeta(), meta: Meta = joinMeta(),
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
@ -141,7 +141,7 @@ public inline fun <T, reified R> Iterable<Data<T>>.foldToData(
/** /**
* Transform an [Iterable] of [NamedData] to a single [Data]. * Transform an [Iterable] of [NamedData] to a single [Data].
*/ */
@DFInternal @UnsafeKType
public inline fun <T, R> Iterable<NamedData<T>>.reduceNamedToData( public inline fun <T, R> Iterable<NamedData<T>>.reduceNamedToData(
outputType: KType, outputType: KType,
meta: Meta = joinMeta(), meta: Meta = joinMeta(),
@ -156,7 +156,7 @@ public inline fun <T, R> Iterable<NamedData<T>>.reduceNamedToData(
transformation(map { it.awaitWithMeta() }) transformation(map { it.awaitWithMeta() })
} }
@OptIn(DFInternal::class) @OptIn(UnsafeKType::class)
public inline fun <T, reified R> Iterable<NamedData<T>>.reduceNamedToData( public inline fun <T, reified R> Iterable<NamedData<T>>.reduceNamedToData(
meta: Meta = joinMeta(), meta: Meta = joinMeta(),
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
@ -181,7 +181,8 @@ public inline fun <T, reified R> Iterable<NamedData<T>>.foldNamedToData(
//DataSet operations //DataSet operations
@DFInternal
@UnsafeKType
public suspend fun <T, R> DataTree<T>.transform( public suspend fun <T, R> DataTree<T>.transform(
outputType: KType, outputType: KType,
metaTransform: MutableMeta.() -> Unit = {}, metaTransform: MutableMeta.() -> Unit = {},
@ -198,7 +199,7 @@ public suspend fun <T, R> DataTree<T>.transform(
} }
} }
@OptIn(DFInternal::class) @OptIn(UnsafeKType::class)
public suspend inline fun <T, reified R> DataTree<T>.transform( public suspend inline fun <T, reified R> DataTree<T>.transform(
noinline metaTransform: MutableMeta.() -> Unit = {}, noinline metaTransform: MutableMeta.() -> Unit = {},
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,

View File

@ -0,0 +1,112 @@
package space.kscience.dataforge.data
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import space.kscience.dataforge.misc.UnsafeKType
import space.kscience.dataforge.names.*
import kotlin.reflect.KType
import kotlin.reflect.typeOf
private class FlatDataTree<T>(
override val dataType: KType,
private val dataSet: Map<Name, Data<T>>,
private val sourceUpdates: Flow<DataUpdate<T>>,
private val prefix: Name,
) : DataTree<T> {
override val data: Data<T>? get() = dataSet[prefix]
override val items: Map<NameToken, FlatDataTree<T>>
get() = dataSet.keys
.filter { it.startsWith(prefix) && it.length > prefix.length }
.map { it.tokens[prefix.length] }
.associateWith { FlatDataTree(dataType, dataSet, sourceUpdates, prefix + it) }
override fun read(name: Name): Data<T>? = dataSet[prefix + name]
override val updates: Flow<DataUpdate<T>> =
sourceUpdates.mapNotNull { update ->
update.name.removeFirstOrNull(prefix)?.let { DataUpdate(dataType, it, update.data) }
}
}
/**
* A builder for static [DataTree].
*/
private class DataTreeBuilder<T>(
private val type: KType,
initialData: Map<Name, Data<T>> = emptyMap(),
) : DataSink<T> {
private val map = HashMap<Name, Data<T>>(initialData)
private val mutex = Mutex()
private val updatesFlow = MutableSharedFlow<DataUpdate<T>>()
override fun put(name: Name, data: Data<T>?) {
if (data == null) {
map.remove(name)
} else {
map[name] = data
}
}
override suspend fun update(name: Name, data: Data<T>?) {
mutex.withLock {
if (data == null) {
map.remove(name)
} else {
map.put(name, data)
}
}
updatesFlow.emit(DataUpdate(data?.type ?: type, name, data))
}
public fun build(): DataTree<T> = FlatDataTree(type, map, updatesFlow, Name.EMPTY)
}
/**
* Create a static [DataTree]
*/
@UnsafeKType
public fun <T> DataTree(
dataType: KType,
generator: DataSink<T>.() -> Unit,
): DataTree<T> = DataTreeBuilder<T>(dataType).apply(generator).build()
/**
* Create and a data tree.
*/
@OptIn(UnsafeKType::class)
public inline fun <reified T> DataTree(
noinline generator: DataSink<T>.() -> Unit,
): DataTree<T> = DataTree(typeOf<T>(), generator)
/**
* Represent this flat data map as a [DataTree] without copying it
*/
@UnsafeKType
public fun <T> Map<Name, Data<T>>.asTree(type: KType): DataTree<T> =
DataTreeBuilder(type, this).build()
/**
* Represent this flat data map as a [DataTree] without copying it
*/
@OptIn(UnsafeKType::class)
public inline fun <reified T> Map<Name, Data<T>>.asTree(): DataTree<T> = asTree(typeOf<T>())
@UnsafeKType
public fun <T> Sequence<NamedData<T>>.toTree(type: KType): DataTree<T> =
DataTreeBuilder(type, associate { it.name to it.data }).build()
/**
* Collect a sequence of [NamedData] to a [DataTree]
*/
@OptIn(UnsafeKType::class)
public inline fun <reified T> Sequence<NamedData<T>>.toTree(): DataTree<T> = toTree(typeOf<T>())

View File

@ -1,22 +1,24 @@
package space.kscience.dataforge.data package space.kscience.dataforge.data
import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
import space.kscience.dataforge.actions.Action import space.kscience.dataforge.actions.Action
import space.kscience.dataforge.actions.invoke import space.kscience.dataforge.actions.invoke
import space.kscience.dataforge.actions.mapping import space.kscience.dataforge.actions.mapping
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.time.Duration.Companion.milliseconds
@OptIn(DFExperimental::class) @OptIn(DFExperimental::class)
internal class ActionsTest { internal class ActionsTest {
@Test @Test
fun testStaticMapAction() = runTest { fun testStaticMapAction() = runTest(timeout = 500.milliseconds) {
val data: DataTree<Int> = DataTree { val data: DataTree<Int> = DataTree {
repeat(10) { repeat(10) {
wrap(it.toString(), it) putValue(it.toString(), it)
} }
} }
@ -28,7 +30,7 @@ internal class ActionsTest {
} }
@Test @Test
fun testDynamicMapAction() = runBlocking { fun testDynamicMapAction() = runTest(timeout = 500.milliseconds) {
val source: MutableDataTree<Int> = MutableDataTree() val source: MutableDataTree<Int> = MutableDataTree()
val plusOne = Action.mapping<Int, Int> { val plusOne = Action.mapping<Int, Int> {
@ -39,13 +41,9 @@ internal class ActionsTest {
repeat(10) { repeat(10) {
source.wrap(it.toString(), it) source.updateValue(it.toString(), it)
} }
result.updates.take(10).onEach { println(it.name) }.collect()
delay(20)
source.close()
result.awaitClose()
assertEquals(2, result["1"]?.await()) assertEquals(2, result["1"]?.await())
} }

View File

@ -0,0 +1,73 @@
package space.kscience.dataforge.data
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.test.runTest
import space.kscience.dataforge.names.asName
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.time.Duration.Companion.milliseconds
internal class DataTreeBuilderTest {
@Test
fun testTreeBuild() = runTest(timeout = 500.milliseconds) {
val node = DataTree<Any> {
putAll("primary") {
putValue("a", "a")
putValue("b", "b")
}
putValue("c.d", "c.d")
putValue("c.f", "c.f")
}
assertEquals("a", node["primary.a"]?.await())
assertEquals("b", node["primary.b"]?.await())
assertEquals("c.d", node["c.d"]?.await())
assertEquals("c.f", node["c.f"]?.await())
}
@Test
fun testDataUpdate() = runTest(timeout = 500.milliseconds) {
val updateData = DataTree<Any> {
putAll("update") {
put("a", Data.wrapValue("a"))
put("b", Data.wrapValue("b"))
}
}
val node = DataTree<Any> {
putAll("primary") {
putValue("a", "a")
putValue("b", "b")
}
putValue("root", "root")
putAll(updateData)
}
assertEquals("a", node["update.a"]?.await())
assertEquals("a", node["primary.a"]?.await())
}
@Test
fun testDynamicUpdates() = runTest(timeout = 500.milliseconds) {
var job: Job? = null
val subNode = MutableDataTree<Int>()
val rootNode = MutableDataTree<Int>() {
job = putAllAndWatch(this@runTest, "sub".asName(), subNode)
}
repeat(10) {
subNode.updateValue("value[$it]", it)
}
rootNode.updates.take(10).collect()
assertEquals(9, rootNode["sub.value[9]"]?.await())
assertEquals(8, rootNode["sub.value[8]"]?.await())
job?.cancel()
}
}

View File

@ -1,6 +1,5 @@
package space.kscience.dataforge.data package space.kscience.dataforge.data
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.misc.DFInternal
@ -25,32 +24,40 @@ private fun <R> Data<*>.castOrNull(type: KType): Data<R>? =
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@DFInternal @DFInternal
public fun <R> Sequence<NamedData<*>>.filterByDataType(type: KType): Sequence<NamedData<R>> = public fun <R> Sequence<DataUpdate<*>>.filterByDataType(type: KType): Sequence<NamedData<R>> =
filter { it.type.isSubtypeOf(type) } as Sequence<NamedData<R>> filter { it.type.isSubtypeOf(type) } as Sequence<NamedData<R>>
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@DFInternal @DFInternal
public fun <R> Flow<NamedData<*>>.filterByDataType(type: KType): Flow<NamedData<R>> = public fun <R> Flow<DataUpdate<*>>.filterByDataType(type: KType): Flow<NamedData<R>> =
filter { it.type.isSubtypeOf(type) } as Flow<NamedData<R>> filter { it.type.isSubtypeOf(type) } as Flow<NamedData<R>>
/** /**
* Select all data matching given type and filters. Does not modify paths * Select all data matching given type and filters. Does not modify paths
* *
* @param predicate additional filtering condition based on item name and meta. By default, accepts all * @param filter additional filtering condition based on item name and meta. By default, accepts all
*/ */
@Suppress("UNCHECKED_CAST")
@DFInternal @DFInternal
public fun <R> DataTree<*>.filterByType( public fun <R> DataTree<*>.filterByType(
type: KType, type: KType,
predicate: DataFilter = DataFilter.EMPTY, branch: Name = Name.EMPTY,
): DataTree<R> = asSequence().filterByDataType<R>(type).filterData(predicate).toTree(type) filter: DataFilter = DataFilter.EMPTY,
): DataTree<R> {
val filterWithType = DataFilter { name, meta, dataType ->
filter.accepts(name, meta, dataType) && dataType.isSubtypeOf(type)
}
return FilteredDataTree(this, filterWithType, branch, type) as DataTree<R>
}
/** /**
* Select a single datum of the appropriate type * Select a single datum of the appropriate type
*/ */
@OptIn(DFInternal::class) @OptIn(DFInternal::class)
public inline fun <reified R : Any> DataTree<*>.filterByType( public inline fun <reified R : Any> DataTree<*>.filterByType(
predicate: DataFilter = DataFilter.EMPTY, branch: Name = Name.EMPTY,
): DataTree<R> = filterByType(typeOf<R>(), predicate) filter: DataFilter = DataFilter.EMPTY,
): DataTree<R> = filterByType(typeOf<R>(), branch, filter = filter)
/** /**
* Select a single datum if it is present and of given [type] * Select a single datum if it is present and of given [type]
@ -63,25 +70,3 @@ public inline fun <reified R : Any> DataTree<*>.getByType(name: Name): NamedData
public inline fun <reified R : Any> DataTree<*>.getByType(name: String): NamedData<R>? = public inline fun <reified R : Any> DataTree<*>.getByType(name: String): NamedData<R>? =
this@getByType.getByType(typeOf<R>(), Name.parse(name)) this@getByType.getByType(typeOf<R>(), Name.parse(name))
/**
* Select all data matching given type and filters. Does not modify paths
*
* @param predicate additional filtering condition based on item name and meta. By default, accepts all
*/
@DFInternal
public fun <R> ObservableDataTree<*>.filterByType(
type: KType,
scope: CoroutineScope,
predicate: DataFilter = DataFilter.EMPTY,
): ObservableDataTree<R> = asSequence()
.filterByDataType<R>(type)
.filterData(predicate)
.toObservableTree(type, scope, updates().filterByDataType<R>(type).filterData(predicate))
@OptIn(DFInternal::class)
public inline fun <reified R> ObservableDataTree<*>.filterByType(
scope: CoroutineScope,
predicate: DataFilter = DataFilter.EMPTY,
): ObservableDataTree<R> = filterByType(typeOf<R>(), scope, predicate)

View File

@ -14,14 +14,14 @@ public infix fun <T : Any> String.put(data: Data<T>): Unit =
* Append node * Append node
*/ */
context(DataSink<T>) context(DataSink<T>)
public infix fun <T : Any> String.put(dataSet: DataTree<T>): Unit = public infix fun <T : Any> String.putAll(dataSet: DataTree<T>): Unit =
putAll(this, dataSet) putAll(this, dataSet)
/** /**
* Build and append node * Build and append node
*/ */
context(DataSink<T>) context(DataSink<T>)
public infix fun <T : Any> String.put( public infix fun <T : Any> String.putAll(
block: DataSink<T>.() -> Unit, block: DataSink<T>.() -> Unit,
): Unit = putAll(Name.parse(this), block) ): Unit = putAll(Name.parse(this), block)

View File

@ -1,68 +0,0 @@
package space.kscience.dataforge.data
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.asName
import kotlin.test.Test
import kotlin.test.assertEquals
internal class DataTreeBuilderTest {
@Test
fun testTreeBuild() = runTest {
val node = DataTree<Any> {
"primary" put {
wrap("a", "a")
wrap("b", "b")
}
wrap("c.d", "c.d")
wrap("c.f", "c.f")
}
assertEquals("a", node["primary.a"]?.await())
assertEquals("b", node["primary.b"]?.await())
assertEquals("c.d", node["c.d"]?.await())
assertEquals("c.f", node["c.f"]?.await())
}
@OptIn(DFExperimental::class)
@Test
fun testDataUpdate() = runTest {
val updateData = DataTree<Any> {
"update" put {
"a" put Data.static("a")
"b" put Data.static("b")
}
}
val node = DataTree<Any> {
"primary" put {
wrap("a", "a")
wrap("b", "b")
}
wrap("root", "root")
putAll(updateData)
}
assertEquals("a", node["update.a"]?.await())
assertEquals("a", node["primary.a"]?.await())
}
@Test
fun testDynamicUpdates() = runBlocking {
val subNode = MutableDataTree<Int>()
val rootNode = MutableDataTree<Int> {
putAllAndWatch("sub".asName(), subNode)
}
repeat(10) {
subNode.wrap("value[$it]", it)
}
delay(20)
assertEquals(9, rootNode["sub.value[9]"]?.await())
}
}

View File

@ -6,7 +6,7 @@ import space.kscience.dataforge.io.IOFormatFactory.Companion.IO_FORMAT_TYPE
import space.kscience.dataforge.io.MetaFormatFactory.Companion.META_FORMAT_TYPE import space.kscience.dataforge.io.MetaFormatFactory.Companion.META_FORMAT_TYPE
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.string import space.kscience.dataforge.meta.string
import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.misc.UnsafeKType
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import kotlin.reflect.KType import kotlin.reflect.KType
import kotlin.reflect.typeOf import kotlin.reflect.typeOf
@ -19,11 +19,11 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@DFInternal @UnsafeKType
public fun <T> resolveIOFormat(type: KType, meta: Meta): IOFormat<T>? = public fun <T> resolveIOFormat(type: KType, meta: Meta): IOFormat<T>? =
ioFormatFactories.singleOrNull { it.type == type }?.build(context, meta) as? IOFormat<T> ioFormatFactories.singleOrNull { it.type == type }?.build(context, meta) as? IOFormat<T>
@OptIn(DFInternal::class) @OptIn(UnsafeKType::class)
public inline fun <reified T> resolveIOFormat(meta: Meta = Meta.EMPTY): IOFormat<T>? = public inline fun <reified T> resolveIOFormat(meta: Meta = Meta.EMPTY): IOFormat<T>? =
resolveIOFormat(typeOf<T>(), meta) resolveIOFormat(typeOf<T>(), meta)

View File

@ -1,3 +1,15 @@
public final class space/kscience/dataforge/meta/ByteArrayValue : java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker, space/kscience/dataforge/meta/Value {
public fun <init> ([B)V
public fun equals (Ljava/lang/Object;)Z
public fun getList ()Ljava/util/List;
public fun getType ()Lspace/kscience/dataforge/meta/ValueType;
public synthetic fun getValue ()Ljava/lang/Object;
public fun getValue ()[B
public fun hashCode ()I
public fun iterator ()Ljava/util/Iterator;
public fun toString ()Ljava/lang/String;
}
public abstract interface class space/kscience/dataforge/meta/Configurable { public abstract interface class space/kscience/dataforge/meta/Configurable {
public abstract fun getMeta ()Lspace/kscience/dataforge/meta/MutableMeta; public abstract fun getMeta ()Lspace/kscience/dataforge/meta/MutableMeta;
} }
@ -30,7 +42,20 @@ public final class space/kscience/dataforge/meta/EnumValue : space/kscience/data
} }
public final class space/kscience/dataforge/meta/ExoticValuesKt { public final class space/kscience/dataforge/meta/ExoticValuesKt {
public static final fun asValue ([B)Lspace/kscience/dataforge/meta/Value;
public static final fun asValue ([D)Lspace/kscience/dataforge/meta/Value; public static final fun asValue ([D)Lspace/kscience/dataforge/meta/Value;
public static final fun byteArray (Lspace/kscience/dataforge/meta/MetaProvider;[BLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
public static final fun byteArray (Lspace/kscience/dataforge/meta/MutableMetaProvider;[BLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
public static synthetic fun byteArray$default (Lspace/kscience/dataforge/meta/MetaProvider;[BLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
public static synthetic fun byteArray$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[BLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
public static final fun doubleArray (Lspace/kscience/dataforge/meta/MetaProvider;[DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
public static final fun doubleArray (Lspace/kscience/dataforge/meta/MutableMetaProvider;[DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
public static synthetic fun doubleArray$default (Lspace/kscience/dataforge/meta/MetaProvider;[DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
public static synthetic fun doubleArray$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
public static final fun getByteArray (Lspace/kscience/dataforge/meta/Meta;)[B
public static final fun getByteArray (Lspace/kscience/dataforge/meta/Value;)[B
public static final fun getDoubleArray (Lspace/kscience/dataforge/meta/Meta;)[D
public static final fun getDoubleArray (Lspace/kscience/dataforge/meta/Value;)[D
public static final fun lazyParseValue (Ljava/lang/String;)Lspace/kscience/dataforge/meta/LazyParsedValue; public static final fun lazyParseValue (Ljava/lang/String;)Lspace/kscience/dataforge/meta/LazyParsedValue;
} }
@ -199,53 +224,56 @@ public final class space/kscience/dataforge/meta/MetaConverterKt {
public static final fun convertNullable (Lspace/kscience/dataforge/meta/MetaConverter;Ljava/lang/Object;)Lspace/kscience/dataforge/meta/Meta; public static final fun convertNullable (Lspace/kscience/dataforge/meta/MetaConverter;Ljava/lang/Object;)Lspace/kscience/dataforge/meta/Meta;
} }
public abstract interface class space/kscience/dataforge/meta/MetaDelegate : kotlin/properties/ReadOnlyProperty, space/kscience/dataforge/meta/descriptors/Described {
}
public final class space/kscience/dataforge/meta/MetaDelegateKt { public final class space/kscience/dataforge/meta/MetaDelegateKt {
public static final fun boolean (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static final fun boolean (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun boolean (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty; public static final fun boolean (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun boolean (Lspace/kscience/dataforge/meta/MetaProvider;ZLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static final fun boolean (Lspace/kscience/dataforge/meta/MetaProvider;ZLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MetaProvider;ZLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MetaProvider;ZLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun double (Lspace/kscience/dataforge/meta/MetaProvider;DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static final fun double (Lspace/kscience/dataforge/meta/MetaProvider;DLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun double (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static final fun double (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MetaProvider;DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MetaProvider;DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun float (Lspace/kscience/dataforge/meta/MetaProvider;FLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static final fun float (Lspace/kscience/dataforge/meta/MetaProvider;FLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun float (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static final fun float (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MetaProvider;FLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MetaProvider;FLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun int (Lspace/kscience/dataforge/meta/MetaProvider;ILspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static final fun int (Lspace/kscience/dataforge/meta/MetaProvider;ILspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun int (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static final fun int (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MetaProvider;ILspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MetaProvider;ILspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun listOfSpec (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static final fun listOfSpec (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun listOfSpec$default (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun listOfSpec$default (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun long (Lspace/kscience/dataforge/meta/MetaProvider;JLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static final fun long (Lspace/kscience/dataforge/meta/MetaProvider;JLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun long (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static final fun long (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MetaProvider;JLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MetaProvider;JLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun node (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
public static final fun node (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaSpec;)Lkotlin/properties/ReadOnlyProperty; public static final fun node (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaSpec;)Lkotlin/properties/ReadOnlyProperty;
public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static final fun node (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaSpec;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaSpec;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty; public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun spec (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun spec$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static final fun spec (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun spec$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty; public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun value (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static final fun value (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadOnlyProperty; public static final fun value (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static final fun value (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate;
} }
public final class space/kscience/dataforge/meta/MetaKt { public final class space/kscience/dataforge/meta/MetaKt {
@ -352,6 +380,7 @@ public abstract interface class space/kscience/dataforge/meta/MutableMeta : spac
public fun put (Ljava/lang/String;Lspace/kscience/dataforge/meta/MetaRepr;)V public fun put (Ljava/lang/String;Lspace/kscience/dataforge/meta/MetaRepr;)V
public fun put (Ljava/lang/String;Lspace/kscience/dataforge/meta/Value;)V public fun put (Ljava/lang/String;Lspace/kscience/dataforge/meta/Value;)V
public fun put (Ljava/lang/String;Z)V public fun put (Ljava/lang/String;Z)V
public fun put (Ljava/lang/String;[B)V
public fun put (Ljava/lang/String;[D)V public fun put (Ljava/lang/String;[D)V
public fun put (Lspace/kscience/dataforge/names/Name;Ljava/lang/Enum;)V public fun put (Lspace/kscience/dataforge/names/Name;Ljava/lang/Enum;)V
public fun put (Lspace/kscience/dataforge/names/Name;Ljava/lang/Number;)V public fun put (Lspace/kscience/dataforge/names/Name;Ljava/lang/Number;)V
@ -371,63 +400,64 @@ public final class space/kscience/dataforge/meta/MutableMeta$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer; public final fun serializer ()Lkotlinx/serialization/KSerializer;
} }
public abstract interface class space/kscience/dataforge/meta/MutableMetaDelegate : kotlin/properties/ReadWriteProperty, space/kscience/dataforge/meta/descriptors/Described {
}
public final class space/kscience/dataforge/meta/MutableMetaDelegateKt { public final class space/kscience/dataforge/meta/MutableMetaDelegateKt {
public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty; public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;ZLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;ZLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;ZLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;ZLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun convertable (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static final fun convertable (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun convertable$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun convertable$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun double (Lspace/kscience/dataforge/meta/MutableMetaProvider;DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static final fun double (Lspace/kscience/dataforge/meta/MutableMetaProvider;DLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun double (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static final fun double (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun doubleArray (Lspace/kscience/dataforge/meta/MutableMetaProvider;[DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static final fun float (Lspace/kscience/dataforge/meta/MutableMetaProvider;FLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun doubleArray$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun float (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun float (Lspace/kscience/dataforge/meta/MutableMetaProvider;FLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;FLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun float (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;FLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun int (Lspace/kscience/dataforge/meta/MutableMetaProvider;ILspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun int (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun int (Lspace/kscience/dataforge/meta/MutableMetaProvider;ILspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;ILspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun int (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;ILspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun listOfConvertable (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun listOfConvertable$default (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun listOfConvertable (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static final fun listValue (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun listOfConvertable$default (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun listValue$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun listValue (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadWriteProperty; public static final fun long (Lspace/kscience/dataforge/meta/MutableMetaProvider;JLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun listValue$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun long (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun long (Lspace/kscience/dataforge/meta/MutableMetaProvider;JLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;JLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun long (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;JLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun node (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaConverter;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun node (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun node (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaConverter;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun node (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaConverter;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun number (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaConverter;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun number (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun number (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static final fun number (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun number (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun number (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun numberList (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun numberList$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun numberList (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static final fun string (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun numberList$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun string (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun string (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static final fun string (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun string (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun string (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun stringList (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun stringList (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun stringList (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun stringList$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun stringList (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun stringList$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun stringList$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun value (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun stringList$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun value (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun value (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static final fun value (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate;
public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
} }
public final class space/kscience/dataforge/meta/MutableMetaKt { public final class space/kscience/dataforge/meta/MutableMetaKt {
@ -447,6 +477,7 @@ public final class space/kscience/dataforge/meta/MutableMetaKt {
public static final fun getOrCreate (Lspace/kscience/dataforge/meta/MutableTypedMeta;Ljava/lang/String;)Lspace/kscience/dataforge/meta/MutableTypedMeta; public static final fun getOrCreate (Lspace/kscience/dataforge/meta/MutableTypedMeta;Ljava/lang/String;)Lspace/kscience/dataforge/meta/MutableTypedMeta;
public static final fun remove (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;)V public static final fun remove (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;)V
public static final fun remove (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)V public static final fun remove (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)V
public static final fun reset (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/Meta;)V
public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Ljava/lang/Iterable;)V public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Ljava/lang/Iterable;)V
public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/meta/Meta;)V public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/meta/Meta;)V
public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Ljava/lang/Iterable;)V public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Ljava/lang/Iterable;)V
@ -703,7 +734,6 @@ public final class space/kscience/dataforge/meta/Value$Companion {
public final class space/kscience/dataforge/meta/ValueExtensionsKt { public final class space/kscience/dataforge/meta/ValueExtensionsKt {
public static final fun getBoolean (Lspace/kscience/dataforge/meta/Value;)Z public static final fun getBoolean (Lspace/kscience/dataforge/meta/Value;)Z
public static final fun getDouble (Lspace/kscience/dataforge/meta/Value;)D public static final fun getDouble (Lspace/kscience/dataforge/meta/Value;)D
public static final fun getDoubleArray (Lspace/kscience/dataforge/meta/Value;)[D
public static final fun getFloat (Lspace/kscience/dataforge/meta/Value;)F public static final fun getFloat (Lspace/kscience/dataforge/meta/Value;)F
public static final fun getInt (Lspace/kscience/dataforge/meta/Value;)I public static final fun getInt (Lspace/kscience/dataforge/meta/Value;)I
public static final fun getLong (Lspace/kscience/dataforge/meta/Value;)J public static final fun getLong (Lspace/kscience/dataforge/meta/Value;)J
@ -722,7 +752,6 @@ public final class space/kscience/dataforge/meta/ValueKt {
public static final fun asValue (Ljava/lang/Number;)Lspace/kscience/dataforge/meta/Value; public static final fun asValue (Ljava/lang/Number;)Lspace/kscience/dataforge/meta/Value;
public static final fun asValue (Ljava/lang/String;)Lspace/kscience/dataforge/meta/Value; public static final fun asValue (Ljava/lang/String;)Lspace/kscience/dataforge/meta/Value;
public static final fun asValue (Z)Lspace/kscience/dataforge/meta/Value; public static final fun asValue (Z)Lspace/kscience/dataforge/meta/Value;
public static final fun asValue ([B)Lspace/kscience/dataforge/meta/Value;
public static final fun asValue ([F)Lspace/kscience/dataforge/meta/Value; public static final fun asValue ([F)Lspace/kscience/dataforge/meta/Value;
public static final fun asValue ([I)Lspace/kscience/dataforge/meta/Value; public static final fun asValue ([I)Lspace/kscience/dataforge/meta/Value;
public static final fun asValue ([J)Lspace/kscience/dataforge/meta/Value; public static final fun asValue ([J)Lspace/kscience/dataforge/meta/Value;
@ -928,6 +957,9 @@ public final class space/kscience/dataforge/misc/NamedKt {
public static final fun isAnonymous (Lspace/kscience/dataforge/misc/Named;)Z public static final fun isAnonymous (Lspace/kscience/dataforge/misc/Named;)Z
} }
public abstract interface annotation class space/kscience/dataforge/misc/UnsafeKType : java/lang/annotation/Annotation {
}
public final class space/kscience/dataforge/names/Name { public final class space/kscience/dataforge/names/Name {
public static final field Companion Lspace/kscience/dataforge/names/Name$Companion; public static final field Companion Lspace/kscience/dataforge/names/Name$Companion;
public static final field NAME_SEPARATOR Ljava/lang/String; public static final field NAME_SEPARATOR Ljava/lang/String;
@ -945,6 +977,16 @@ public final class space/kscience/dataforge/names/Name$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer; public final fun serializer ()Lkotlinx/serialization/KSerializer;
} }
public final class space/kscience/dataforge/names/NameIndexComparator : java/util/Comparator {
public static final field INSTANCE Lspace/kscience/dataforge/names/NameIndexComparator;
public synthetic fun compare (Ljava/lang/Object;Ljava/lang/Object;)I
public fun compare (Ljava/lang/String;Ljava/lang/String;)I
}
public final class space/kscience/dataforge/names/NameIndexComparatorKt {
public static final fun getIndexedList (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/names/Name;)Ljava/util/List;
}
public final class space/kscience/dataforge/names/NameKt { public final class space/kscience/dataforge/names/NameKt {
public static final fun appendFirst (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)Lspace/kscience/dataforge/names/Name; public static final fun appendFirst (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)Lspace/kscience/dataforge/names/Name;
public static final fun appendLeft (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)Lspace/kscience/dataforge/names/Name; public static final fun appendLeft (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)Lspace/kscience/dataforge/names/Name;

View File

@ -135,16 +135,17 @@ public interface MetaConverter<T>: MetaSpec<T> {
@DFExperimental @DFExperimental
public inline fun <reified T> serializable( public inline fun <reified T> serializable(
descriptor: MetaDescriptor? = null, descriptor: MetaDescriptor? = null,
jsonEncoder: Json = Json,
): MetaConverter<T> = object : MetaConverter<T> { ): MetaConverter<T> = object : MetaConverter<T> {
private val serializer: KSerializer<T> = serializer() private val serializer: KSerializer<T> = serializer()
override fun readOrNull(source: Meta): T? { override fun readOrNull(source: Meta): T? {
val json = source.toJson(descriptor) val json = source.toJson(descriptor)
return Json.decodeFromJsonElement(serializer, json) return jsonEncoder.decodeFromJsonElement(serializer, json)
} }
override fun convert(obj: T): Meta { override fun convert(obj: T): Meta {
val json = Json.encodeToJsonElement(obj) val json = jsonEncoder.encodeToJsonElement(obj)
return json.toMeta(descriptor) return json.toMeta(descriptor)
} }

View File

@ -1,15 +1,27 @@
package space.kscience.dataforge.meta package space.kscience.dataforge.meta
import space.kscience.dataforge.meta.descriptors.Described
import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.asName
import kotlin.properties.ReadOnlyProperty import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
/* Meta delegates */ /* Meta delegates */
public fun MetaProvider.node(key: Name? = null): ReadOnlyProperty<Any?, Meta?> = ReadOnlyProperty { _, property -> public interface MetaDelegate<T> : ReadOnlyProperty<Any?, T>, Described
get(key ?: property.name.asName())
public fun MetaProvider.node(
key: Name? = null,
descriptor: MetaDescriptor? = null,
): MetaDelegate<Meta?> = object : MetaDelegate<Meta?> {
override val descriptor: MetaDescriptor? = descriptor
override fun getValue(thisRef: Any?, property: KProperty<*>): Meta? {
return get(key ?: property.name.asName())
}
} }
/** /**
@ -18,8 +30,12 @@ public fun MetaProvider.node(key: Name? = null): ReadOnlyProperty<Any?, Meta?> =
public fun <T> MetaProvider.spec( public fun <T> MetaProvider.spec(
metaSpec: MetaSpec<T>, metaSpec: MetaSpec<T>,
key: Name? = null, key: Name? = null,
): ReadOnlyProperty<Any?, T?> = ReadOnlyProperty { _, property -> ): MetaDelegate<T?> = object : MetaDelegate<T?> {
get(key ?: property.name.asName())?.let { metaSpec.read(it) } override val descriptor: MetaDescriptor? get() = metaSpec.descriptor
override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
return get(key ?: property.name.asName())?.let { metaSpec.read(it) }
}
} }
/** /**
@ -27,9 +43,9 @@ public fun <T> MetaProvider.spec(
*/ */
@DFExperimental @DFExperimental
public inline fun <reified T> MetaProvider.serializable( public inline fun <reified T> MetaProvider.serializable(
descriptor: MetaDescriptor? = null,
key: Name? = null, key: Name? = null,
): ReadOnlyProperty<Any?, T?> = spec(MetaConverter.serializable(descriptor), key) descriptor: MetaDescriptor? = null,
): MetaDelegate<T?> = spec(MetaConverter.serializable(descriptor), key)
@Deprecated("Use convertable", ReplaceWith("convertable(converter, key)")) @Deprecated("Use convertable", ReplaceWith("convertable(converter, key)"))
public fun <T> MetaProvider.node( public fun <T> MetaProvider.node(
@ -43,78 +59,90 @@ public fun <T> MetaProvider.node(
public fun <T> Meta.listOfSpec( public fun <T> Meta.listOfSpec(
converter: MetaSpec<T>, converter: MetaSpec<T>,
key: Name? = null, key: Name? = null,
): ReadOnlyProperty<Any?, List<T>> = ReadOnlyProperty{_, property -> ): MetaDelegate<List<T>> = object : MetaDelegate<List<T>> {
override fun getValue(thisRef: Any?, property: KProperty<*>): List<T> {
val name = key ?: property.name.asName() val name = key ?: property.name.asName()
getIndexed(name).values.map { converter.read(it) } return getIndexed(name).values.map { converter.read(it) }
}
override val descriptor: MetaDescriptor? = converter.descriptor?.copy(multiple = true)
} }
@DFExperimental @DFExperimental
public inline fun <reified T> Meta.listOfSerializable( public inline fun <reified T> Meta.listOfSerializable(
descriptor: MetaDescriptor? = null,
key: Name? = null, key: Name? = null,
): ReadOnlyProperty<Any?, List<T>> = listOfSpec(MetaConverter.serializable(descriptor), key) descriptor: MetaDescriptor? = null,
): MetaDelegate<List<T>> = listOfSpec(MetaConverter.serializable(descriptor), key)
/** /**
* A property delegate that uses custom key * A property delegate that uses custom key
*/ */
public fun MetaProvider.value(key: Name? = null): ReadOnlyProperty<Any?, Value?> = ReadOnlyProperty { _, property -> public fun MetaProvider.value(
get(key ?: property.name.asName())?.value key: Name? = null,
descriptor: MetaDescriptor? = null,
): MetaDelegate<Value?> = object : MetaDelegate<Value?> {
override fun getValue(thisRef: Any?, property: KProperty<*>): Value? = get(key ?: property.name.asName())?.value
override val descriptor: MetaDescriptor? = descriptor
} }
public fun <R> MetaProvider.value( public fun <R> MetaProvider.value(
key: Name? = null, key: Name? = null,
descriptor: MetaDescriptor? = null,
reader: (Value?) -> R, reader: (Value?) -> R,
): ReadOnlyProperty<Any?, R> = ReadOnlyProperty { _, property -> ): MetaDelegate<R> = object : MetaDelegate<R> {
reader(get(key ?: property.name.asName())?.value) override fun getValue(thisRef: Any?, property: KProperty<*>): R = reader(get(key ?: property.name.asName())?.value)
override val descriptor: MetaDescriptor? = descriptor
} }
//TODO add caching for sealed nodes //TODO add caching for sealed nodes
/* Read-only delegates for [Meta] */ /* Read-only delegates for [Meta] */
public fun MetaProvider.string(key: Name? = null): ReadOnlyProperty<Any?, String?> = value(key) { it?.string } public fun MetaProvider.string(key: Name? = null): MetaDelegate<String?> = value(key = key) { it?.string }
public fun MetaProvider.boolean(key: Name? = null): ReadOnlyProperty<Any?, Boolean?> = value(key) { it?.boolean } public fun MetaProvider.boolean(key: Name? = null): MetaDelegate<Boolean?> = value(key = key) { it?.boolean }
public fun MetaProvider.number(key: Name? = null): ReadOnlyProperty<Any?, Number?> = value(key) { it?.numberOrNull } public fun MetaProvider.number(key: Name? = null): MetaDelegate<Number?> = value(key = key) { it?.numberOrNull }
public fun MetaProvider.double(key: Name? = null): ReadOnlyProperty<Any?, Double?> = value(key) { it?.double } public fun MetaProvider.double(key: Name? = null): MetaDelegate<Double?> = value(key = key) { it?.double }
public fun MetaProvider.float(key: Name? = null): ReadOnlyProperty<Any?, Float?> = value(key) { it?.float } public fun MetaProvider.float(key: Name? = null): MetaDelegate<Float?> = value(key = key) { it?.float }
public fun MetaProvider.int(key: Name? = null): ReadOnlyProperty<Any?, Int?> = value(key) { it?.int } public fun MetaProvider.int(key: Name? = null): MetaDelegate<Int?> = value(key = key) { it?.int }
public fun MetaProvider.long(key: Name? = null): ReadOnlyProperty<Any?, Long?> = value(key) { it?.long } public fun MetaProvider.long(key: Name? = null): MetaDelegate<Long?> = value(key = key) { it?.long }
public fun MetaProvider.string(default: String, key: Name? = null): ReadOnlyProperty<Any?, String> = public fun MetaProvider.string(default: String, key: Name? = null): MetaDelegate<String> =
value(key) { it?.string ?: default } value(key = key) { it?.string ?: default }
public fun MetaProvider.boolean(default: Boolean, key: Name? = null): ReadOnlyProperty<Any?, Boolean> = public fun MetaProvider.boolean(default: Boolean, key: Name? = null): MetaDelegate<Boolean> =
value(key) { it?.boolean ?: default } value(key = key) { it?.boolean ?: default }
public fun MetaProvider.number(default: Number, key: Name? = null): ReadOnlyProperty<Any?, Number> = public fun MetaProvider.number(default: Number, key: Name? = null): MetaDelegate<Number> =
value(key) { it?.numberOrNull ?: default } value(key = key) { it?.numberOrNull ?: default }
public fun MetaProvider.double(default: Double, key: Name? = null): ReadOnlyProperty<Any?, Double> = public fun MetaProvider.double(default: Double, key: Name? = null): MetaDelegate<Double> =
value(key) { it?.double ?: default } value(key = key) { it?.double ?: default }
public fun MetaProvider.float(default: Float, key: Name? = null): ReadOnlyProperty<Any?, Float> = public fun MetaProvider.float(default: Float, key: Name? = null): MetaDelegate<Float> =
value(key) { it?.float ?: default } value(key = key) { it?.float ?: default }
public fun MetaProvider.int(default: Int, key: Name? = null): ReadOnlyProperty<Any?, Int> = public fun MetaProvider.int(default: Int, key: Name? = null): MetaDelegate<Int> =
value(key) { it?.int ?: default } value(key = key) { it?.int ?: default }
public fun MetaProvider.long(default: Long, key: Name? = null): ReadOnlyProperty<Any?, Long> = public fun MetaProvider.long(default: Long, key: Name? = null): MetaDelegate<Long> =
value(key) { it?.long ?: default } value(key = key) { it?.long ?: default }
public inline fun <reified E : Enum<E>> MetaProvider.enum(default: E, key: Name? = null): ReadOnlyProperty<Any?, E> = public inline fun <reified E : Enum<E>> MetaProvider.enum(default: E, key: Name? = null): MetaDelegate<E> =
value<E>(key) { it?.enum<E>() ?: default } value<E>(key = key) { it?.enum<E>() ?: default }
public fun MetaProvider.string(key: Name? = null, default: () -> String): ReadOnlyProperty<Any?, String> = public fun MetaProvider.string(key: Name? = null, default: () -> String): MetaDelegate<String> =
value(key) { it?.string ?: default() } value(key = key) { it?.string ?: default() }
public fun MetaProvider.boolean(key: Name? = null, default: () -> Boolean): ReadOnlyProperty<Any?, Boolean> = public fun MetaProvider.boolean(key: Name? = null, default: () -> Boolean): MetaDelegate<Boolean> =
value(key) { it?.boolean ?: default() } value(key = key) { it?.boolean ?: default() }
public fun MetaProvider.number(key: Name? = null, default: () -> Number): ReadOnlyProperty<Any?, Number> = public fun MetaProvider.number(key: Name? = null, default: () -> Number): MetaDelegate<Number> =
value(key) { it?.numberOrNull ?: default() } value(key = key) { it?.numberOrNull ?: default() }

View File

@ -128,6 +128,10 @@ public interface MutableMeta : Meta, MutableMetaProvider {
setValue(Name.parse(this), array.asValue()) setValue(Name.parse(this), array.asValue())
} }
public infix fun String.put(array: ByteArray) {
setValue(Name.parse(this), array.asValue())
}
public infix fun String.put(repr: MetaRepr) { public infix fun String.put(repr: MetaRepr) {
set(Name.parse(this), repr.toMeta()) set(Name.parse(this), repr.toMeta())
} }

View File

@ -1,5 +1,6 @@
package space.kscience.dataforge.meta package space.kscience.dataforge.meta
import space.kscience.dataforge.meta.descriptors.Described
import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
@ -8,10 +9,18 @@ import space.kscience.dataforge.names.getIndexedList
import kotlin.properties.ReadWriteProperty import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
/* Read-write delegates */ /* Read-write delegates */
public fun MutableMetaProvider.node(key: Name? = null): ReadWriteProperty<Any?, Meta?> = public interface MutableMetaDelegate<T> : ReadWriteProperty<Any?, T>, Described
object : ReadWriteProperty<Any?, Meta?> {
public fun MutableMetaProvider.node(
key: Name? = null,
descriptor: MetaDescriptor? = null,
): MutableMetaDelegate<Meta?> = object : MutableMetaDelegate<Meta?> {
override val descriptor: MetaDescriptor? = descriptor
override fun getValue(thisRef: Any?, property: KProperty<*>): Meta? { override fun getValue(thisRef: Any?, property: KProperty<*>): Meta? {
return get(key ?: property.name.asName()) return get(key ?: property.name.asName())
} }
@ -20,7 +29,7 @@ public fun MutableMetaProvider.node(key: Name? = null): ReadWriteProperty<Any?,
val name = key ?: property.name.asName() val name = key ?: property.name.asName()
set(name, value) set(name, value)
} }
} }
/** /**
* Use [converter] to transform an object to Meta and back. * Use [converter] to transform an object to Meta and back.
@ -29,8 +38,11 @@ public fun MutableMetaProvider.node(key: Name? = null): ReadWriteProperty<Any?,
public fun <T> MutableMetaProvider.convertable( public fun <T> MutableMetaProvider.convertable(
converter: MetaConverter<T>, converter: MetaConverter<T>,
key: Name? = null, key: Name? = null,
): ReadWriteProperty<Any?, T?> = ): MutableMetaDelegate<T?> = object : MutableMetaDelegate<T?> {
object : ReadWriteProperty<Any?, T?> {
override val descriptor: MetaDescriptor? get() = converter.descriptor
override fun getValue(thisRef: Any?, property: KProperty<*>): T? { override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
val name = key ?: property.name.asName() val name = key ?: property.name.asName()
return get(name)?.let { converter.read(it) } return get(name)?.let { converter.read(it) }
@ -40,10 +52,10 @@ public fun <T> MutableMetaProvider.convertable(
val name = key ?: property.name.asName() val name = key ?: property.name.asName()
set(name, value?.let { converter.convert(it) }) set(name, value?.let { converter.convert(it) })
} }
} }
@Deprecated("Use convertable", ReplaceWith("convertable(converter, key)")) @Deprecated("Use convertable", ReplaceWith("convertable(converter, key)"))
public fun <T> MutableMetaProvider.node(key: Name? = null, converter: MetaConverter<T>): ReadWriteProperty<Any?, T?> = public fun <T> MutableMetaProvider.node(key: Name? = null, converter: MetaConverter<T>): MutableMetaDelegate<T?> =
convertable(converter, key) convertable(converter, key)
/** /**
@ -54,7 +66,7 @@ public fun <T> MutableMetaProvider.node(key: Name? = null, converter: MetaConver
public inline fun <reified T> MutableMetaProvider.serializable( public inline fun <reified T> MutableMetaProvider.serializable(
descriptor: MetaDescriptor? = null, descriptor: MetaDescriptor? = null,
key: Name? = null, key: Name? = null,
): ReadWriteProperty<Any?, T?> = convertable(MetaConverter.serializable(descriptor), key) ): MutableMetaDelegate<T?> = convertable(MetaConverter.serializable(descriptor), key)
/** /**
* Use [converter] to convert a list of same name siblings meta to object and back. * Use [converter] to convert a list of same name siblings meta to object and back.
@ -63,7 +75,9 @@ public inline fun <reified T> MutableMetaProvider.serializable(
public fun <T> MutableMeta.listOfConvertable( public fun <T> MutableMeta.listOfConvertable(
converter: MetaConverter<T>, converter: MetaConverter<T>,
key: Name? = null, key: Name? = null,
): ReadWriteProperty<Any?, List<T>> = object : ReadWriteProperty<Any?, List<T>> { ): MutableMetaDelegate<List<T>> = object : MutableMetaDelegate<List<T>> {
override val descriptor: MetaDescriptor? = converter.descriptor?.copy(multiple = true)
override fun getValue(thisRef: Any?, property: KProperty<*>): List<T> { override fun getValue(thisRef: Any?, property: KProperty<*>): List<T> {
val name = key ?: property.name.asName() val name = key ?: property.name.asName()
return getIndexedList(name).map { converter.read(it) } return getIndexedList(name).map { converter.read(it) }
@ -77,26 +91,33 @@ public fun <T> MutableMeta.listOfConvertable(
@DFExperimental @DFExperimental
public inline fun <reified T> MutableMeta.listOfSerializable( public inline fun <reified T> MutableMeta.listOfSerializable(
descriptor: MetaDescriptor? = null,
key: Name? = null, key: Name? = null,
): ReadWriteProperty<Any?, List<T>> = listOfConvertable(MetaConverter.serializable(descriptor), key) descriptor: MetaDescriptor? = null,
): MutableMetaDelegate<List<T>> = listOfConvertable(MetaConverter.serializable(descriptor), key)
public fun MutableMetaProvider.value(key: Name? = null): ReadWriteProperty<Any?, Value?> = public fun MutableMetaProvider.value(
object : ReadWriteProperty<Any?, Value?> { key: Name? = null,
descriptor: MetaDescriptor? = null,
): MutableMetaDelegate<Value?> = object : MutableMetaDelegate<Value?> {
override val descriptor: MetaDescriptor? = descriptor
override fun getValue(thisRef: Any?, property: KProperty<*>): Value? = override fun getValue(thisRef: Any?, property: KProperty<*>): Value? =
get(key ?: property.name.asName())?.value get(key ?: property.name.asName())?.value
override fun setValue(thisRef: Any?, property: KProperty<*>, value: Value?) { override fun setValue(thisRef: Any?, property: KProperty<*>, value: Value?) {
setValue(key ?: property.name.asName(), value) setValue(key ?: property.name.asName(), value)
} }
} }
public fun <T> MutableMetaProvider.value( public fun <T> MutableMetaProvider.value(
key: Name? = null, key: Name? = null,
writer: (T) -> Value? = { Value.of(it) }, writer: (T) -> Value? = { Value.of(it) },
descriptor: MetaDescriptor? = null,
reader: (Value?) -> T, reader: (Value?) -> T,
): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> { ): MutableMetaDelegate<T> = object : MutableMetaDelegate<T> {
override val descriptor: MetaDescriptor? = descriptor
override fun getValue(thisRef: Any?, property: KProperty<*>): T = override fun getValue(thisRef: Any?, property: KProperty<*>): T =
reader(get(key ?: property.name.asName())?.value) reader(get(key ?: property.name.asName())?.value)
@ -107,65 +128,65 @@ public fun <T> MutableMetaProvider.value(
/* Read-write delegates for [MutableItemProvider] */ /* Read-write delegates for [MutableItemProvider] */
public fun MutableMetaProvider.string(key: Name? = null): ReadWriteProperty<Any?, String?> = public fun MutableMetaProvider.string(key: Name? = null): MutableMetaDelegate<String?> =
value(key) { it?.string } value(key) { it?.string }
public fun MutableMetaProvider.boolean(key: Name? = null): ReadWriteProperty<Any?, Boolean?> = public fun MutableMetaProvider.boolean(key: Name? = null): MutableMetaDelegate<Boolean?> =
value(key) { it?.boolean } value(key) { it?.boolean }
public fun MutableMetaProvider.number(key: Name? = null): ReadWriteProperty<Any?, Number?> = public fun MutableMetaProvider.number(key: Name? = null): MutableMetaDelegate<Number?> =
value(key) { it?.number } value(key) { it?.number }
public fun MutableMetaProvider.string(default: String, key: Name? = null): ReadWriteProperty<Any?, String> = public fun MutableMetaProvider.string(default: String, key: Name? = null): MutableMetaDelegate<String> =
value(key) { it?.string ?: default } value(key) { it?.string ?: default }
public fun MutableMetaProvider.boolean(default: Boolean, key: Name? = null): ReadWriteProperty<Any?, Boolean> = public fun MutableMetaProvider.boolean(default: Boolean, key: Name? = null): MutableMetaDelegate<Boolean> =
value(key) { it?.boolean ?: default } value(key) { it?.boolean ?: default }
public fun MutableMetaProvider.number(default: Number, key: Name? = null): ReadWriteProperty<Any?, Number> = public fun MutableMetaProvider.number(default: Number, key: Name? = null): MutableMetaDelegate<Number> =
value(key) { it?.number ?: default } value(key) { it?.number ?: default }
public fun MutableMetaProvider.string(key: Name? = null, default: () -> String): ReadWriteProperty<Any?, String> = public fun MutableMetaProvider.string(key: Name? = null, default: () -> String): MutableMetaDelegate<String> =
value(key) { it?.string ?: default() } value(key) { it?.string ?: default() }
public fun MutableMetaProvider.boolean(key: Name? = null, default: () -> Boolean): ReadWriteProperty<Any?, Boolean> = public fun MutableMetaProvider.boolean(key: Name? = null, default: () -> Boolean): MutableMetaDelegate<Boolean> =
value(key) { it?.boolean ?: default() } value(key) { it?.boolean ?: default() }
public fun MutableMetaProvider.number(key: Name? = null, default: () -> Number): ReadWriteProperty<Any?, Number> = public fun MutableMetaProvider.number(key: Name? = null, default: () -> Number): MutableMetaDelegate<Number> =
value(key) { it?.number ?: default() } value(key) { it?.number ?: default() }
public inline fun <reified E : Enum<E>> MutableMetaProvider.enum( public inline fun <reified E : Enum<E>> MutableMetaProvider.enum(
default: E, default: E,
key: Name? = null, key: Name? = null,
): ReadWriteProperty<Any?, E> = value(key) { value -> value?.string?.let { enumValueOf<E>(it) } ?: default } ): MutableMetaDelegate<E> = value(key) { value -> value?.string?.let { enumValueOf<E>(it) } ?: default }
/* Number delegates */ /* Number delegates */
public fun MutableMetaProvider.int(key: Name? = null): ReadWriteProperty<Any?, Int?> = public fun MutableMetaProvider.int(key: Name? = null): MutableMetaDelegate<Int?> =
value(key) { it?.int } value(key) { it?.int }
public fun MutableMetaProvider.double(key: Name? = null): ReadWriteProperty<Any?, Double?> = public fun MutableMetaProvider.double(key: Name? = null): MutableMetaDelegate<Double?> =
value(key) { it?.double } value(key) { it?.double }
public fun MutableMetaProvider.long(key: Name? = null): ReadWriteProperty<Any?, Long?> = public fun MutableMetaProvider.long(key: Name? = null): MutableMetaDelegate<Long?> =
value(key) { it?.long } value(key) { it?.long }
public fun MutableMetaProvider.float(key: Name? = null): ReadWriteProperty<Any?, Float?> = public fun MutableMetaProvider.float(key: Name? = null): MutableMetaDelegate<Float?> =
value(key) { it?.float } value(key) { it?.float }
/* Safe number delegates*/ /* Safe number delegates*/
public fun MutableMetaProvider.int(default: Int, key: Name? = null): ReadWriteProperty<Any?, Int> = public fun MutableMetaProvider.int(default: Int, key: Name? = null): MutableMetaDelegate<Int> =
value(key) { it?.int ?: default } value(key) { it?.int ?: default }
public fun MutableMetaProvider.double(default: Double, key: Name? = null): ReadWriteProperty<Any?, Double> = public fun MutableMetaProvider.double(default: Double, key: Name? = null): MutableMetaDelegate<Double> =
value(key) { it?.double ?: default } value(key) { it?.double ?: default }
public fun MutableMetaProvider.long(default: Long, key: Name? = null): ReadWriteProperty<Any?, Long> = public fun MutableMetaProvider.long(default: Long, key: Name? = null): MutableMetaDelegate<Long> =
value(key) { it?.long ?: default } value(key) { it?.long ?: default }
public fun MutableMetaProvider.float(default: Float, key: Name? = null): ReadWriteProperty<Any?, Float> = public fun MutableMetaProvider.float(default: Float, key: Name? = null): MutableMetaDelegate<Float> =
value(key) { it?.float ?: default } value(key) { it?.float ?: default }
@ -174,7 +195,7 @@ public fun MutableMetaProvider.float(default: Float, key: Name? = null): ReadWri
public fun MutableMetaProvider.stringList( public fun MutableMetaProvider.stringList(
vararg default: String, vararg default: String,
key: Name? = null, key: Name? = null,
): ReadWriteProperty<Any?, List<String>> = value( ): MutableMetaDelegate<List<String>> = value(
key, key,
writer = { list -> list.map { str -> str.asValue() }.asValue() }, writer = { list -> list.map { str -> str.asValue() }.asValue() },
reader = { it?.stringList ?: listOf(*default) }, reader = { it?.stringList ?: listOf(*default) },
@ -182,7 +203,7 @@ public fun MutableMetaProvider.stringList(
public fun MutableMetaProvider.stringList( public fun MutableMetaProvider.stringList(
key: Name? = null, key: Name? = null,
): ReadWriteProperty<Any?, List<String>?> = value( ): MutableMetaDelegate<List<String>?> = value(
key, key,
writer = { it -> it?.map { str -> str.asValue() }?.asValue() }, writer = { it -> it?.map { str -> str.asValue() }?.asValue() },
reader = { it?.stringList }, reader = { it?.stringList },
@ -191,29 +212,18 @@ public fun MutableMetaProvider.stringList(
public fun MutableMetaProvider.numberList( public fun MutableMetaProvider.numberList(
vararg default: Number, vararg default: Number,
key: Name? = null, key: Name? = null,
): ReadWriteProperty<Any?, List<Number>> = value( ): MutableMetaDelegate<List<Number>> = value(
key, key,
writer = { it.map { num -> num.asValue() }.asValue() }, writer = { it.map { num -> num.asValue() }.asValue() },
reader = { it?.list?.map { value -> value.numberOrNull ?: Double.NaN } ?: listOf(*default) }, reader = { it?.list?.map { value -> value.numberOrNull ?: Double.NaN } ?: listOf(*default) },
) )
/* A special delegate for double arrays */
public fun MutableMetaProvider.doubleArray(
vararg default: Double,
key: Name? = null,
): ReadWriteProperty<Any?, DoubleArray> = value(
key,
writer = { DoubleArrayValue(it) },
reader = { it?.doubleArray ?: doubleArrayOf(*default) },
)
public fun <T> MutableMetaProvider.listValue( public fun <T> MutableMetaProvider.listValue(
key: Name? = null, key: Name? = null,
writer: (T) -> Value = { Value.of(it) }, writer: (T) -> Value = { Value.of(it) },
reader: (Value) -> T, reader: (Value) -> T,
): ReadWriteProperty<Any?, List<T>?> = value( ): MutableMetaDelegate<List<T>?> = value(
key, key,
writer = { it?.map(writer)?.asValue() }, writer = { it?.map(writer)?.asValue() },
reader = { it?.list?.map(reader) } reader = { it?.list?.map(reader) }

View File

@ -122,7 +122,7 @@ public open class Scheme(
override fun hashCode(): Int = Meta.hashCode(this) override fun hashCode(): Int = Meta.hashCode(this)
override fun set(name: Name, node: Meta?) { override fun set(name: Name, node: Meta?) {
target[name] = node target[pathName + name] = node
invalidate(name) invalidate(name)
} }

View File

@ -256,8 +256,6 @@ public fun ShortArray.asValue(): Value = if (isEmpty()) Null else ListValue(map
public fun FloatArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) }) public fun FloatArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
public fun ByteArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
public fun <E : Enum<E>> E.asValue(): Value = EnumValue(this) public fun <E : Enum<E>> E.asValue(): Value = EnumValue(this)

View File

@ -1,5 +1,9 @@
package space.kscience.dataforge.meta package space.kscience.dataforge.meta
import space.kscience.dataforge.names.Name
import kotlin.properties.ReadOnlyProperty
import kotlin.properties.ReadWriteProperty
/** /**
* A value built from string which content and type are parsed on-demand * A value built from string which content and type are parsed on-demand
@ -44,3 +48,79 @@ public class DoubleArrayValue(override val value: DoubleArray) : Value, Iterable
} }
public fun DoubleArray.asValue(): Value = if (isEmpty()) Null else DoubleArrayValue(this) public fun DoubleArray.asValue(): Value = if (isEmpty()) Null else DoubleArrayValue(this)
public val Value.doubleArray: DoubleArray
get() = if (this is DoubleArrayValue) {
value
} else {
DoubleArray(list.size) { list[it].double }
}
public val Meta?.doubleArray: DoubleArray? get() = this?.value?.doubleArray
public fun MetaProvider.doubleArray(
vararg default: Double,
key: Name? = null,
): ReadOnlyProperty<Any?, DoubleArray> = value(
key,
reader = { it?.doubleArray ?: doubleArrayOf(*default) },
)
public fun MutableMetaProvider.doubleArray(
vararg default: Double,
key: Name? = null,
): ReadWriteProperty<Any?, DoubleArray> = value(
key,
writer = { DoubleArrayValue(it) },
reader = { it?.doubleArray ?: doubleArrayOf(*default) },
)
public class ByteArrayValue(override val value: ByteArray) : Value, Iterable<Byte> {
override val type: ValueType get() = ValueType.LIST
override val list: List<Value> get() = value.map { NumberValue(it) }
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Value) return false
return when (other) {
is ByteArrayValue -> value.contentEquals(other.value)
else -> list == other.list
}
}
override fun hashCode(): Int = value.contentHashCode()
override fun toString(): String = list.joinToString(prefix = "[", postfix = "]")
override fun iterator(): Iterator<Byte> = value.iterator()
}
public fun ByteArray.asValue(): Value = ByteArrayValue(this)
public val Value.byteArray: ByteArray
get() = if (this is ByteArrayValue) {
value
} else {
ByteArray(list.size) { list[it].number.toByte() }
}
public val Meta?.byteArray: ByteArray? get() = this?.value?.byteArray
public fun MetaProvider.byteArray(
vararg default: Byte,
key: Name? = null,
): ReadOnlyProperty<Any?, ByteArray> = value(
key,
reader = { it?.byteArray ?: byteArrayOf(*default) },
)
public fun MutableMetaProvider.byteArray(
vararg default: Byte,
key: Name? = null,
): ReadWriteProperty<Any?, ByteArray> = value(
key,
writer = { ByteArrayValue(it) },
reader = { it?.byteArray ?: byteArrayOf(*default) },
)

View File

@ -31,12 +31,5 @@ public inline fun <reified E : Enum<E>> Value.enum(): E = if (this is EnumValue<
public val Value.stringList: List<String> get() = list.map { it.string } public val Value.stringList: List<String> get() = list.map { it.string }
public val Value.doubleArray: DoubleArray
get() = if (this is DoubleArrayValue) {
value
} else {
DoubleArray(list.size) { list[it].double }
}
public fun Value.toMeta(): Meta = Meta(this) public fun Value.toMeta(): Meta = Meta(this)

View File

@ -19,3 +19,10 @@ public annotation class DFExperimental
@RequiresOptIn(level = RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Retention(AnnotationRetention.BINARY) @Retention(AnnotationRetention.BINARY)
public annotation class DFInternal public annotation class DFInternal
/**
* Annotation marks methods that explicitly use KType without checking that it corresponds to the type parameter
*/
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Retention(AnnotationRetention.BINARY)
public annotation class UnsafeKType

View File

@ -69,7 +69,7 @@ public class NameToken(public val body: String, public val index: String? = null
public fun parse(string: String): NameToken { public fun parse(string: String): NameToken {
val body = string.substringBefore('[') val body = string.substringBefore('[')
val index = string.substringAfter('[', "") val index = string.substringAfter('[', "")
if (index.isNotEmpty() && index.endsWith(']')) error("NameToken with index must end with ']'") if (index.isNotEmpty() && !index.endsWith(']')) error("NameToken with index must end with ']'")
return NameToken(body, index.removeSuffix("]")) return NameToken(body, index.removeSuffix("]"))
} }
} }

View File

@ -1,70 +0,0 @@
package space.kscience.dataforge.meta
import space.kscience.dataforge.misc.DFExperimental
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
private class SchemeWithInit: Scheme(){
init {
set("initial", "initialValue")
}
var initial by string()
companion object: SchemeSpec<SchemeWithInit>(::SchemeWithInit)
}
class SchemeTest {
@Test
fun testSchemeWrappingBeforeEdit() {
val config = MutableMeta()
val scheme = TestScheme.write(config)
scheme.a = 29
assertEquals(29, config["a"].int)
}
@OptIn(DFExperimental::class)
@Test
fun testSchemeWrappingAfterEdit() {
val scheme = TestScheme.empty()
scheme.a = 29
val config = MutableMeta()
scheme.retarget(config)
assertEquals(29, scheme.a)
}
@Test
fun testSchemeSubscription() {
val scheme = TestScheme.empty()
var flag: Int? = null
scheme.useProperty(TestScheme::a) { a ->
flag = a
}
scheme.a = 2
assertEquals(2, flag)
}
@Test
fun testListSubscription(){
val scheme = TestScheme.empty()
var value: Value? = null
scheme.v = ListValue(0.0,0.0,0.0)
scheme.useProperty(TestScheme::v){
value = it
}
scheme.v = ListValue(1.0, 2.0, 3.0)
assertNotNull(value)
}
@Test
fun testSchemeWithInit(){
val scheme = SchemeWithInit()
assertEquals("initialValue", scheme.initial)
scheme.initial = "none"
assertEquals("none", scheme.initial)
}
}

View File

@ -1,7 +1,17 @@
package space.kscience.dataforge.meta package space.kscience.dataforge.meta
import space.kscience.dataforge.misc.DFExperimental
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNotNull
internal class SubScheme : Scheme() {
var subValue by string()
companion object : SchemeSpec<SubScheme>(::SubScheme)
}
internal class TestScheme : Scheme() { internal class TestScheme : Scheme() {
var list by numberList(1, 2, 3) var list by numberList(1, 2, 3)
@ -11,9 +21,23 @@ internal class TestScheme : Scheme() {
var v by value() var v by value()
var sub by scheme(SubScheme)
companion object : SchemeSpec<TestScheme>(::TestScheme) companion object : SchemeSpec<TestScheme>(::TestScheme)
} }
private class SchemeWithInit: Scheme(){
init {
set("initial", "initialValue")
}
var initial by string()
companion object: SchemeSpec<SchemeWithInit>(::SchemeWithInit)
}
class SpecificationTest { class SpecificationTest {
// @Test // @Test
@ -71,4 +95,64 @@ class SpecificationTest {
assertEquals(22, config["child.a"].int) assertEquals(22, config["child.a"].int)
assertEquals("test", config["child.b"].string) assertEquals("test", config["child.b"].string)
} }
@Test
fun testSchemeWrappingBeforeEdit() {
val config = MutableMeta()
val scheme = TestScheme.write(config)
scheme.a = 29
assertEquals(29, config["a"].int)
}
@OptIn(DFExperimental::class)
@Test
fun testSchemeWrappingAfterEdit() {
val scheme = TestScheme.empty()
scheme.a = 29
val config = MutableMeta()
scheme.retarget(config)
assertEquals(29, scheme.a)
}
@Test
fun testSchemeSubscription() {
val scheme = TestScheme.empty()
var flag: Int? = null
scheme.useProperty(TestScheme::a) { a ->
flag = a
}
scheme.a = 2
assertEquals(2, flag)
}
@Test
fun testListSubscription(){
val scheme = TestScheme.empty()
var value: Value? = null
scheme.v = ListValue(0.0,0.0,0.0)
scheme.useProperty(TestScheme::v){
value = it
}
scheme.v = ListValue(1.0, 2.0, 3.0)
assertNotNull(value)
}
@Test
fun testSubScheme(){
val scheme = TestScheme.empty()
scheme.sub.subValue = "aaa"
assertEquals("aaa",scheme.sub.subValue)
}
@Test
fun testSchemeWithInit(){
val scheme = SchemeWithInit()
assertEquals("initialValue", scheme.initial)
scheme.initial = "none"
assertEquals("none", scheme.initial)
}
} }

View File

@ -1,9 +1,6 @@
package space.kscience.dataforge.names package space.kscience.dataforge.names
import kotlin.test.Test import kotlin.test.*
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class NameTest { class NameTest {
@Test @Test
@ -50,4 +47,19 @@ class NameTest {
val name = Name.parse("a.b.c") val name = Name.parse("a.b.c")
assertEquals("a.b".parseAsName(), name.cutLast()) assertEquals("a.b".parseAsName(), name.cutLast())
} }
@Test
fun tokenParseTest(){
val token1 = NameToken.parse("token[index]")
assertEquals("token", token1.body)
assertEquals("index", token1.index)
val token2 = NameToken.parse("token-body")
assertEquals("token-body", token2.body)
assertEquals("", token2.index)
assertFails {
NameToken.parse("token[22")
}
}
} }

View File

@ -0,0 +1,24 @@
package space.kscience.dataforge.values
import space.kscience.dataforge.meta.DoubleArrayValue
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.doubleArray
import space.kscience.dataforge.meta.get
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class DoubleArrayValue {
@Test
fun doubleArrayWriteRead(){
val meta = Meta{
"doubleArray" put doubleArrayOf(1.0,2.0,3.0)
}
assertTrue {
meta["doubleArray"]?.value is DoubleArrayValue
}
assertEquals(2.0, meta["doubleArray"].doubleArray?.get(1))
}
}

View File

@ -10,6 +10,7 @@ import space.kscience.dataforge.meta.MetaSpec
import space.kscience.dataforge.meta.descriptors.Described import space.kscience.dataforge.meta.descriptors.Described
import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.misc.DfType import space.kscience.dataforge.misc.DfType
import space.kscience.dataforge.misc.UnsafeKType
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.workspace.Task.Companion.TYPE import space.kscience.dataforge.workspace.Task.Companion.TYPE
import kotlin.reflect.KType import kotlin.reflect.KType
@ -90,7 +91,8 @@ public fun <T : Any> Task(
taskMeta: Meta, taskMeta: Meta,
): TaskResult<T> { ): TaskResult<T> {
//TODO use safe builder and check for external data on add and detects cycles //TODO use safe builder and check for external data on add and detects cycles
val dataset = MutableDataTree<T>(resultType, workspace.context).apply { @OptIn(UnsafeKType::class)
val dataset = MutableDataTree<T>(resultType).apply {
TaskResultBuilder(workspace, taskName, taskMeta, this).apply { TaskResultBuilder(workspace, taskName, taskMeta, this).apply {
withContext(GoalExecutionRestriction() + workspace.goalLogger) { withContext(GoalExecutionRestriction() + workspace.goalLogger) {
builder() builder()
@ -98,7 +100,6 @@ public fun <T : Any> Task(
} }
} }
return workspace.wrapResult(dataset, taskName, taskMeta) return workspace.wrapResult(dataset, taskName, taskMeta)
} }
} }
@ -117,6 +118,7 @@ public inline fun <reified T : Any> Task(
* @param builder for resulting data set * @param builder for resulting data set
*/ */
@Suppress("FunctionName") @Suppress("FunctionName")
public fun <T : Any, C : MetaRepr> Task( public fun <T : Any, C : MetaRepr> Task(
resultType: KType, resultType: KType,
@ -132,7 +134,8 @@ public fun <T : Any, C : MetaRepr> Task(
): TaskResult<T> = withContext(GoalExecutionRestriction() + workspace.goalLogger) { ): TaskResult<T> = withContext(GoalExecutionRestriction() + workspace.goalLogger) {
//TODO use safe builder and check for external data on add and detects cycles //TODO use safe builder and check for external data on add and detects cycles
val taskMeta = configuration.toMeta() val taskMeta = configuration.toMeta()
val dataset = MutableDataTree<T>(resultType, this).apply { @OptIn(UnsafeKType::class)
val dataset = MutableDataTree<T>(resultType).apply {
TaskResultBuilder(workspace, taskName, taskMeta, this).apply { builder(configuration) } TaskResultBuilder(workspace, taskName, taskMeta, this).apply { builder(configuration) }
} }
workspace.wrapResult(dataset, taskName, taskMeta) workspace.wrapResult(dataset, taskName, taskMeta)

View File

@ -4,7 +4,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.joinAll import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import space.kscience.dataforge.data.ObservableDataTree import space.kscience.dataforge.data.DataTree
import space.kscience.dataforge.data.asSequence import space.kscience.dataforge.data.asSequence
import space.kscience.dataforge.data.launch import space.kscience.dataforge.data.launch
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
@ -17,16 +17,16 @@ import space.kscience.dataforge.names.Name
* @param taskMeta The configuration of the task that produced the result * @param taskMeta The configuration of the task that produced the result
*/ */
public data class TaskResult<T>( public data class TaskResult<T>(
public val content: ObservableDataTree<T>, public val content: DataTree<T>,
public val workspace: Workspace, public val workspace: Workspace,
public val taskName: Name, public val taskName: Name,
public val taskMeta: Meta, public val taskMeta: Meta,
) : ObservableDataTree<T> by content ) : DataTree<T> by content
/** /**
* Wrap data into [TaskResult] * Wrap data into [TaskResult]
*/ */
public fun <T> Workspace.wrapResult(data: ObservableDataTree<T>, taskName: Name, taskMeta: Meta): TaskResult<T> = public fun <T> Workspace.wrapResult(data: DataTree<T>, taskName: Name, taskMeta: Meta): TaskResult<T> =
TaskResult(data, this, taskName, taskMeta) TaskResult(data, this, taskName, taskMeta)
/** /**

View File

@ -2,7 +2,10 @@ package space.kscience.dataforge.workspace
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import space.kscience.dataforge.context.ContextAware import space.kscience.dataforge.context.ContextAware
import space.kscience.dataforge.data.* import space.kscience.dataforge.data.Data
import space.kscience.dataforge.data.DataTree
import space.kscience.dataforge.data.asSequence
import space.kscience.dataforge.data.get
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.meta.MutableMeta
import space.kscience.dataforge.misc.DfType import space.kscience.dataforge.misc.DfType
@ -26,7 +29,7 @@ public interface Workspace : ContextAware, Provider, CoroutineScope {
/** /**
* The whole data node for current workspace * The whole data node for current workspace
*/ */
public val data: ObservableDataTree<*> public val data: DataTree<*>
/** /**
* All targets associated with the workspace * All targets associated with the workspace

View File

@ -1,6 +1,5 @@
package space.kscience.dataforge.workspace package space.kscience.dataforge.workspace
import kotlinx.coroutines.CoroutineScope
import space.kscience.dataforge.actions.Action import space.kscience.dataforge.actions.Action
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.ContextBuilder import space.kscience.dataforge.context.ContextBuilder
@ -12,6 +11,7 @@ import space.kscience.dataforge.meta.*
import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.MetaDescriptorBuilder import space.kscience.dataforge.meta.descriptors.MetaDescriptorBuilder
import space.kscience.dataforge.misc.DFBuilder import space.kscience.dataforge.misc.DFBuilder
import space.kscience.dataforge.misc.UnsafeKType
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.asName
import kotlin.collections.set import kotlin.collections.set
@ -98,19 +98,19 @@ public inline fun <reified T : Any> TaskContainer.task(
public inline fun <T : Any, reified R : Any> TaskContainer.action( public inline fun <T : Any, reified R : Any> TaskContainer.action(
selector: DataSelector<T>, selector: DataSelector<T>,
action: Action<T, R>, action: Action<T, R>,
noinline metaTransform: MutableMeta.()-> Unit = {}, noinline metaTransform: MutableMeta.() -> Unit = {},
noinline descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {}, noinline descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {},
): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, TaskReference<R>>> = ): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, TaskReference<R>>> =
task(MetaDescriptor(descriptorBuilder)) { task(MetaDescriptor(descriptorBuilder)) {
result(action.execute(from(selector), taskMeta.copy(metaTransform))) result(action.execute(from(selector), taskMeta.copy(metaTransform), workspace))
} }
public class WorkspaceBuilder( public class WorkspaceBuilder(
private val parentContext: Context = Global, private val parentContext: Context = Global,
private val coroutineScope: CoroutineScope = parentContext,
) : TaskContainer { ) : TaskContainer {
private var context: Context? = null private var context: Context? = null
private val data = MutableDataTree<Any?>(typeOf<Any?>(), coroutineScope) @OptIn(UnsafeKType::class)
private val data = MutableDataTree<Any?>(typeOf<Any?>())
private val targets: HashMap<String, Meta> = HashMap() private val targets: HashMap<String, Meta> = HashMap()
private val tasks = HashMap<Name, Task<*>>() private val tasks = HashMap<Name, Task<*>>()
private var cache: WorkspaceCache? = null private var cache: WorkspaceCache? = null

View File

@ -2,14 +2,14 @@ package space.kscience.dataforge.workspace
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.gather import space.kscience.dataforge.context.gather
import space.kscience.dataforge.data.ObservableDataTree import space.kscience.dataforge.data.DataTree
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
internal class WorkspaceImpl internal constructor( internal class WorkspaceImpl internal constructor(
override val context: Context, override val context: Context,
override val data: ObservableDataTree<*>, override val data: DataTree<*>,
override val targets: Map<String, Meta>, override val targets: Map<String, Meta>,
tasks: Map<Name, Task<*>>, tasks: Map<Name, Task<*>>,
private val postProcess: suspend (TaskResult<*>) -> TaskResult<*>, private val postProcess: suspend (TaskResult<*>) -> TaskResult<*>,

View File

@ -3,14 +3,14 @@ package space.kscience.dataforge.workspace
import space.kscience.dataforge.data.Data import space.kscience.dataforge.data.Data
import space.kscience.dataforge.data.await import space.kscience.dataforge.data.await
import space.kscience.dataforge.io.* import space.kscience.dataforge.io.*
import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.misc.UnsafeKType
import kotlin.reflect.typeOf import kotlin.reflect.typeOf
/** /**
* Convert an [Envelope] to a data via given format. The actual parsing is done lazily. * Convert an [Envelope] to a data via given format. The actual parsing is done lazily.
*/ */
@OptIn(DFInternal::class) @OptIn(UnsafeKType::class)
public inline fun <reified T : Any> Envelope.toData(format: IOReader<T>): Data<T> = Data(typeOf<T>(), meta) { public inline fun <reified T : Any> Envelope.toData(format: IOReader<T>): Data<T> = Data(typeOf<T>(), meta) {
data?.readWith(format) ?: error("Can't convert envelope without data to Data") data?.readWith(format) ?: error("Can't convert envelope without data to Data")
} }

View File

@ -113,7 +113,7 @@ public suspend inline fun <T, reified R> TaskResultBuilder<R>.actionFrom(
action: Action<T, R>, action: Action<T, R>,
dependencyMeta: Meta = defaultDependencyMeta, dependencyMeta: Meta = defaultDependencyMeta,
) { ) {
this.putAll(action.execute(from(selector, dependencyMeta), dependencyMeta)) putAll(action.execute(from(selector, dependencyMeta), dependencyMeta, workspace))
} }

View File

@ -0,0 +1,19 @@
package space.kscience.dataforge.workspace
import space.kscience.dataforge.actions.AbstractAction
import space.kscience.dataforge.data.*
import space.kscience.dataforge.meta.Meta
import kotlin.reflect.KType
internal class CachingAction<T>(type: KType, private val caching: (NamedData<T>) -> NamedData<T>) :
AbstractAction<T, T>(type) {
override fun DataSink<T>.generate(source: DataTree<T>, meta: Meta) {
source.forEach {
put(caching(it))
}
}
override suspend fun DataSink<T>.update(source: DataTree<T>, meta: Meta, updatedData: DataUpdate<T>) {
put(updatedData.name, updatedData.data?.named(updatedData.name)?.let(caching))
}
}

View File

@ -1,19 +1,22 @@
package space.kscience.dataforge.workspace package space.kscience.dataforge.workspace
import kotlinx.coroutines.flow.map
import kotlinx.io.* import kotlinx.io.*
import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.protobuf.ProtoBuf import kotlinx.serialization.protobuf.ProtoBuf
import kotlinx.serialization.serializer import kotlinx.serialization.serializer
import space.kscience.dataforge.actions.Action
import space.kscience.dataforge.actions.invoke
import space.kscience.dataforge.context.error import space.kscience.dataforge.context.error
import space.kscience.dataforge.context.logger import space.kscience.dataforge.context.logger
import space.kscience.dataforge.context.request import space.kscience.dataforge.context.request
import space.kscience.dataforge.data.* import space.kscience.dataforge.data.Data
import space.kscience.dataforge.data.await
import space.kscience.dataforge.data.named
import space.kscience.dataforge.io.* import space.kscience.dataforge.io.*
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.misc.UnsafeKType
import space.kscience.dataforge.names.withIndex import space.kscience.dataforge.names.withIndex
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.deleteIfExists import kotlin.io.path.deleteIfExists
@ -51,7 +54,8 @@ public class FileWorkspaceCache(public val cacheDirectory: Path) : WorkspaceCach
// private fun <T : Any> TaskData<*>.checkType(taskType: KType): TaskData<T> = this as TaskData<T> // private fun <T : Any> TaskData<*>.checkType(taskType: KType): TaskData<T> = this as TaskData<T>
@OptIn(DFExperimental::class, DFInternal::class)
@OptIn(DFExperimental::class, UnsafeKType::class)
override suspend fun <T> cache(result: TaskResult<T>): TaskResult<T> { override suspend fun <T> cache(result: TaskResult<T>): TaskResult<T> {
val io = result.workspace.context.request(IOPlugin) val io = result.workspace.context.request(IOPlugin)
@ -59,8 +63,8 @@ public class FileWorkspaceCache(public val cacheDirectory: Path) : WorkspaceCach
?: ProtobufIOFormat(result.dataType) ?: ProtobufIOFormat(result.dataType)
?: error("Can't resolve IOFormat for ${result.dataType}") ?: error("Can't resolve IOFormat for ${result.dataType}")
fun cacheOne(data: NamedData<T>): NamedData<T> {
val cachingAction: Action<T, T> = CachingAction(result.dataType) { data ->
val path = cacheDirectory / val path = cacheDirectory /
result.taskName.withIndex(result.taskMeta.hashCode().toString(16)).toString() / result.taskName.withIndex(result.taskMeta.hashCode().toString(16)).toString() /
data.name.toString() data.name.toString()
@ -79,7 +83,7 @@ public class FileWorkspaceCache(public val cacheDirectory: Path) : WorkspaceCach
} }
} }
//waiting for data in current scope because Envelope is synchronous //waiting for data in the current scope because Envelope is synchronous
return@Data data.await().also { result -> return@Data data.await().also { result ->
val envelope = Envelope { val envelope = Envelope {
meta = data.meta meta = data.meta
@ -91,12 +95,10 @@ public class FileWorkspaceCache(public val cacheDirectory: Path) : WorkspaceCach
} }
} }
return datum.named(data.name) datum.named(data.name)
} }
val cachedTree = cachingAction(result)
val cachedTree = result.asSequence().map { cacheOne(it) }
.toObservableTree(result.dataType, result.workspace, result.updates().map { cacheOne(it) })
return result.workspace.wrapResult(cachedTree, result.taskName, result.taskMeta) return result.workspace.wrapResult(cachedTree, result.taskName, result.taskMeta)
} }

View File

@ -1,8 +1,11 @@
package space.kscience.dataforge.workspace package space.kscience.dataforge.workspace
import kotlinx.coroutines.flow.map import space.kscience.dataforge.actions.Action
import space.kscience.dataforge.data.* import space.kscience.dataforge.actions.invoke
import space.kscience.dataforge.data.Data
import space.kscience.dataforge.data.named
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import kotlin.reflect.KType import kotlin.reflect.KType
import kotlin.reflect.full.isSubtypeOf import kotlin.reflect.full.isSubtypeOf
@ -19,19 +22,18 @@ public class InMemoryWorkspaceCache : WorkspaceCache {
if (type.isSubtypeOf(taskType)) this as Data<T> if (type.isSubtypeOf(taskType)) this as Data<T>
else error("Cached data type mismatch: expected $taskType but got $type") else error("Cached data type mismatch: expected $taskType but got $type")
@OptIn(DFExperimental::class)
override suspend fun <T> cache(result: TaskResult<T>): TaskResult<T> { override suspend fun <T> cache(result: TaskResult<T>): TaskResult<T> {
fun cacheOne(data: NamedData<T>): NamedData<T> { val cachingAction: Action<T, T> = CachingAction(result.dataType) { data ->
val cachedData = cache.getOrPut(TaskResultId(result.taskName, result.taskMeta)){ val cachedData = cache.getOrPut(TaskResultId(result.taskName, result.taskMeta)){
HashMap() HashMap()
}.getOrPut(data.name){ }.getOrPut(data.name){
data.data data.data
} }
return cachedData.checkType<T>(result.dataType).named(data.name) cachedData.checkType<T>(result.dataType).named(data.name)
} }
val cachedTree = cachingAction(result)
val cachedTree = result.asSequence().map { cacheOne(it) }
.toObservableTree(result.dataType, result.workspace, result.updates().map { cacheOne(it) })
return result.workspace.wrapResult(cachedTree, result.taskName, result.taskMeta) return result.workspace.wrapResult(cachedTree, result.taskName, result.taskMeta)
} }

View File

@ -7,14 +7,12 @@ import space.kscience.dataforge.data.StaticData
import space.kscience.dataforge.io.* import space.kscience.dataforge.io.*
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.copy import space.kscience.dataforge.meta.copy
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.NameToken import space.kscience.dataforge.names.NameToken
import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.asName
import space.kscience.dataforge.names.plus import space.kscience.dataforge.names.plus
import java.nio.file.Files import java.nio.file.*
import java.nio.file.Path
import java.nio.file.StandardWatchEventKinds
import java.nio.file.WatchEvent
import java.nio.file.attribute.BasicFileAttributes import java.nio.file.attribute.BasicFileAttributes
import java.nio.file.spi.FileSystemProvider import java.nio.file.spi.FileSystemProvider
import kotlin.io.path.* import kotlin.io.path.*
@ -166,15 +164,25 @@ public fun DataSink<Binary>.monitorFiles(
* @param resources The names of the resources to read. * @param resources The names of the resources to read.
* @param classLoader The class loader to use for loading the resources. By default, it uses the current thread's context class loader. * @param classLoader The class loader to use for loading the resources. By default, it uses the current thread's context class loader.
*/ */
@DFExperimental
public fun DataSink<Binary>.resources( public fun DataSink<Binary>.resources(
io: IOPlugin, io: IOPlugin,
vararg resources: String, resource: String,
vararg otherResources: String,
classLoader: ClassLoader = Thread.currentThread().contextClassLoader, classLoader: ClassLoader = Thread.currentThread().contextClassLoader,
) { ) {
resources.forEach { resource -> //create a file system if necessary
val path = classLoader.getResource(resource)?.toURI()?.toPath() ?: error( val uri = Thread.currentThread().contextClassLoader.getResource("common")!!.toURI()
"Resource with name $resource is not resolved" try {
uri.toPath()
} catch (e: FileSystemNotFoundException) {
FileSystems.newFileSystem(uri, mapOf("create" to "true"))
}
listOf(resource,*otherResources).forEach { r ->
val path = classLoader.getResource(r)?.toURI()?.toPath() ?: error(
"Resource with name $r is not resolved"
) )
files(io, resource.asName(), path) files(io, r.asName(), path)
} }
} }

View File

@ -3,7 +3,7 @@ package space.kscience.dataforge.workspace
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import space.kscience.dataforge.data.wrap import space.kscience.dataforge.data.putValue
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.boolean import space.kscience.dataforge.meta.boolean
import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.get
@ -22,7 +22,7 @@ internal class CachingWorkspaceTest {
data { data {
//statically initialize data //statically initialize data
repeat(5) { repeat(5) {
wrap("myData[$it]", it) putValue("myData[$it]", it)
} }
} }

View File

@ -47,7 +47,7 @@ class DataPropagationTest {
} }
data { data {
repeat(100) { repeat(100) {
wrap("myData[$it]", it) putValue("myData[$it]", it)
} }
} }
} }

View File

@ -24,11 +24,11 @@ import kotlin.test.assertEquals
class FileDataTest { class FileDataTest {
val dataNode = DataTree<String> { val dataNode = DataTree<String> {
putAll("dir") { putAll("dir") {
wrap("a", "Some string") { putValue("a", "Some string") {
"content" put "Some string" "content" put "Some string"
} }
} }
wrap("b", "root data") putValue("b", "root data")
// meta { // meta {
// "content" put "This is root meta node" // "content" put "This is root meta node"
// } // }

View File

@ -3,11 +3,11 @@ package space.kscience.dataforge.workspace
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import space.kscience.dataforge.data.wrap import space.kscience.dataforge.data.putValue
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import java.nio.file.Files import java.nio.file.Files
@OptIn(ExperimentalCoroutinesApi::class,DFExperimental::class) @OptIn(ExperimentalCoroutinesApi::class, DFExperimental::class)
class FileWorkspaceCacheTest { class FileWorkspaceCacheTest {
@Test @Test
@ -16,7 +16,7 @@ class FileWorkspaceCacheTest {
data { data {
//statically initialize data //statically initialize data
repeat(5) { repeat(5) {
wrap("myData[$it]", it) putValue("myData[$it]", it)
} }
} }
fileCache(Files.createTempDirectory("dataforge-temporary-cache")) fileCache(Files.createTempDirectory("dataforge-temporary-cache"))

View File

@ -6,7 +6,6 @@ package space.kscience.dataforge.workspace
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Timeout
import space.kscience.dataforge.context.* import space.kscience.dataforge.context.*
import space.kscience.dataforge.data.* import space.kscience.dataforge.data.*
import space.kscience.dataforge.meta.* import space.kscience.dataforge.meta.*
@ -16,6 +15,7 @@ import space.kscience.dataforge.names.plus
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertTrue import kotlin.test.assertTrue
import kotlin.time.Duration.Companion.milliseconds
/** /**
@ -62,7 +62,7 @@ internal class SimpleWorkspaceTest {
data { data {
//statically initialize data //statically initialize data
repeat(100) { repeat(100) {
wrap("myData[$it]", it) putValue("myData[$it]", it)
} }
} }
@ -148,18 +148,16 @@ internal class SimpleWorkspaceTest {
} }
@Test @Test
@Timeout(1) fun testWorkspace() = runTest(timeout = 100.milliseconds) {
fun testWorkspace() = runTest {
val node = workspace.produce("sum") val node = workspace.produce("sum")
val res = node.asSequence().single() val res = node.asSequence().single()
assertEquals(328350, res.await()) assertEquals(328350, res.await())
} }
@Test @Test
@Timeout(1) fun testMetaPropagation() = runTest(timeout = 100.milliseconds) {
fun testMetaPropagation() = runTest {
val node = workspace.produce("sum") { "testFlag" put true } val node = workspace.produce("sum") { "testFlag" put true }
val res = node.single().await() val res = node["sum"]!!.await()
} }
@Test @Test
@ -188,7 +186,7 @@ internal class SimpleWorkspaceTest {
val node = workspace.produce("filterOne") { val node = workspace.produce("filterOne") {
"name" put "myData[12]" "name" put "myData[12]"
} }
assertEquals(12, node.single().await()) assertEquals(12, node.asSequence().first().await())
} }
} }