diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d89307a..7cc1c21d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,12 @@ ### Added - Wasm artifacts - Add automatic MetaConverter for serializeable objects +- Add Meta and MutableMeta delegates for convertable and serializeable ### Changed ### Deprecated +- `node(key,converter)` in favor of `serializable` delegate ### Removed diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt index 73923d56..42e4fe14 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt @@ -1,6 +1,8 @@ package space.kscience.dataforge.meta +import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import kotlin.properties.ReadOnlyProperty @@ -11,13 +13,48 @@ public fun MetaProvider.node(key: Name? = null): ReadOnlyProperty = get(key ?: property.name.asName()) } -public fun MetaProvider.node( +/** + * Use [converter] to read the Meta node + */ +public fun MetaProvider.convertable( + converter: MetaConverter, key: Name? = null, - converter: MetaConverter ): ReadOnlyProperty = ReadOnlyProperty { _, property -> get(key ?: property.name.asName())?.let { converter.metaToObject(it) } } +/** + * Use object serializer to transform it to Meta and back + */ +@DFExperimental +public inline fun MetaProvider.serializable( + descriptor: MetaDescriptor? = null, + key: Name? = null, +): ReadOnlyProperty = convertable(MetaConverter.serializable(descriptor), key) + +@Deprecated("Use convertable", ReplaceWith("convertable(converter, key)")) +public fun MetaProvider.node( + key: Name? = null, + converter: MetaConverter, +): ReadOnlyProperty = convertable(converter, key) + +/** + * Use [converter] to convert a list of same name siblings meta to object + */ +public fun Meta.listOfConvertable( + converter: MetaConverter, + key: Name? = null, +): ReadOnlyProperty> = ReadOnlyProperty{_, property -> + val name = key ?: property.name.asName() + getIndexed(name).values.map { converter.metaToObject(it) } +} + +@DFExperimental +public inline fun Meta.listOfSerializable( + descriptor: MetaDescriptor? = null, + key: Name? = null, +): ReadOnlyProperty> = listOfConvertable(MetaConverter.serializable(descriptor), key) + /** * A property delegate that uses custom key */ @@ -27,7 +64,7 @@ public fun MetaProvider.value(key: Name? = null): ReadOnlyProperty public fun MetaProvider.value( key: Name? = null, - reader: (Value?) -> R + reader: (Value?) -> R, ): ReadOnlyProperty = ReadOnlyProperty { _, property -> reader(get(key ?: property.name.asName())?.value) } diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt index 7e05d215..24a09240 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt @@ -165,7 +165,7 @@ public fun MutableMetaProvider.remove(key: String) { // node setters -public operator fun MutableMetaProvider.set(Key: NameToken, value: Meta): Unit = set(Key.asName(), value) +public operator fun MutableMetaProvider.set(key: NameToken, value: Meta): Unit = set(key.asName(), value) public operator fun MutableMetaProvider.set(key: String, value: Meta): Unit = set(Name.parse(key), value) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt index 0f28523c..d77348dd 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt @@ -1,6 +1,8 @@ package space.kscience.dataforge.meta +import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import kotlin.properties.ReadWriteProperty @@ -20,10 +22,18 @@ public fun MutableMetaProvider.node(key: Name? = null): ReadWriteProperty MutableMetaProvider.node(key: Name? = null, converter: MetaConverter): ReadWriteProperty = +/** + * Use [converter] to transform an object to Meta and back. + * Note that mutation of the object does not change Meta. + */ +public fun MutableMetaProvider.convertable( + converter: MetaConverter, + key: Name? = null, +): ReadWriteProperty = object : ReadWriteProperty { override fun getValue(thisRef: Any?, property: KProperty<*>): T? { - return get(key ?: property.name.asName())?.let { converter.metaToObject(it) } + val name = key ?: property.name.asName() + return get(name)?.let { converter.metaToObject(it) } } override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) { @@ -32,6 +42,46 @@ public fun MutableMetaProvider.node(key: Name? = null, converter: MetaConver } } +@Deprecated("Use convertable", ReplaceWith("convertable(converter, key)")) +public fun MutableMetaProvider.node(key: Name? = null, converter: MetaConverter): ReadWriteProperty = + convertable(converter, key) + +/** + * Use object serializer to transform it to Meta and back. + * Note that mutation of the object does not change Meta. + */ +@DFExperimental +public inline fun MutableMetaProvider.serializable( + descriptor: MetaDescriptor? = null, + key: Name? = null, +): ReadWriteProperty = convertable(MetaConverter.serializable(descriptor), key) + +/** + * Use [converter] to convert a list of same name siblings meta to object and back. + * Note that mutation of the object does not change Meta. + */ +public fun MutableMeta.listOfConvertable( + converter: MetaConverter, + key: Name? = null, +): ReadWriteProperty> = object : ReadWriteProperty> { + override fun getValue(thisRef: Any?, property: KProperty<*>): List { + val name = key ?: property.name.asName() + return getIndexed(name).values.map { converter.metaToObject(it) } + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: List) { + val name = key ?: property.name.asName() + setIndexed(name, value.map { converter.objectToMeta(it) }) + } +} + +@DFExperimental +public inline fun MutableMeta.listOfSerializable( + descriptor: MetaDescriptor? = null, + key: Name? = null, +): ReadWriteProperty> = listOfConvertable(MetaConverter.serializable(descriptor), key) + + public fun MutableMetaProvider.value(key: Name? = null): ReadWriteProperty = object : ReadWriteProperty { override fun getValue(thisRef: Any?, property: KProperty<*>): Value? = @@ -45,7 +95,7 @@ public fun MutableMetaProvider.value(key: Name? = null): ReadWriteProperty MutableMetaProvider.value( key: Name? = null, writer: (T) -> Value? = { Value.of(it) }, - reader: (Value?) -> T + reader: (Value?) -> T, ): ReadWriteProperty = object : ReadWriteProperty { override fun getValue(thisRef: Any?, property: KProperty<*>): T = reader(get(key ?: property.name.asName())?.value)