From 81abbe28a940a93c2d0478009a357b80decccd59 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 11 Aug 2021 18:03:06 +0300 Subject: [PATCH] Add fast cast for recursive generics --- .../space/kscience/dataforge/meta/Meta.kt | 13 +++++---- .../meta/descriptors/MetaDescriptor.kt | 27 ++++++++++--------- .../space/kscience/dataforge/misc/cast.kt | 3 +++ .../space/kscience/dataforge/misc/castJs.kt | 5 ++++ .../space/kscience/dataforge/misc/castJvm.kt | 4 +++ .../kscience/dataforge/misc/castNative.kt | 4 +++ 6 files changed, 36 insertions(+), 20 deletions(-) create mode 100644 dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/cast.kt create mode 100644 dataforge-meta/src/jsMain/kotlin/space/kscience/dataforge/misc/castJs.kt create mode 100644 dataforge-meta/src/jvmMain/kotlin/space/kscience/dataforge/misc/castJvm.kt create mode 100644 dataforge-meta/src/nativeMain/kotlin/space/kscience/dataforge/misc/castNative.kt diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt index c8313512..48a65c6d 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt @@ -3,6 +3,7 @@ package space.kscience.dataforge.meta import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import space.kscience.dataforge.misc.Type +import space.kscience.dataforge.misc.unsafeCast import space.kscience.dataforge.names.* import space.kscience.dataforge.values.* @@ -139,13 +140,6 @@ public fun Meta.getIndexed(name: Name): Map { */ public interface TypedMeta> : Meta { - /** - * Access self as a recursive type instance - */ - @Suppress("UNCHECKED_CAST") - public val self: M - get() = this as M - override val items: Map override fun getMeta(name: Name): M? { @@ -161,6 +155,11 @@ public interface TypedMeta> : Meta { override fun toMeta(): Meta = this } +/** + * Access self as a recursive type instance + */ +public inline val > TypedMeta.self: M get() = unsafeCast() + //public typealias Meta = TypedMeta<*> public operator fun > TypedMeta.get(token: NameToken): M? = items[token] diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptor.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptor.kt index bad10e9a..cbce3e2b 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptor.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptor.kt @@ -51,6 +51,20 @@ public data class MetaDescriptor( public val defaultValue: Value? = null, public val attributes: Meta = Meta.EMPTY, ) { + /** + * A node constructed of default values for this descriptor and its children + */ + public val defaultNode: Meta by lazy { + Meta { + defaultValue?.let { defaultValue -> + this.value = defaultValue + } + children.forEach { (key, descriptor) -> + set(key, descriptor.defaultNode) + } + } + } + public companion object { internal const val ALLOWED_VALUES_KEY = "allowedValues" } @@ -68,19 +82,6 @@ public operator fun MetaDescriptor.get(name: Name): MetaDescriptor? = when (name public operator fun MetaDescriptor.get(name: String): MetaDescriptor? = get(Name.parse(name)) -/** - * A node constructed of default values for this descriptor and its children - */ -public val MetaDescriptor.defaultNode: Meta - get() = Meta { - defaultValue?.let { defaultValue -> - this.value = defaultValue - } - children.forEach { (key, descriptor) -> - set(key, descriptor.defaultNode) - } - } - public fun MetaDescriptor.validate(value: Value?): Boolean = if (value == null) { valueRequirement != ValueRequirement.REQUIRED } else { diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/cast.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/cast.kt new file mode 100644 index 00000000..e714d596 --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/cast.kt @@ -0,0 +1,3 @@ +package space.kscience.dataforge.misc + +public expect inline fun Any?.unsafeCast(): T \ No newline at end of file diff --git a/dataforge-meta/src/jsMain/kotlin/space/kscience/dataforge/misc/castJs.kt b/dataforge-meta/src/jsMain/kotlin/space/kscience/dataforge/misc/castJs.kt new file mode 100644 index 00000000..b404ebb4 --- /dev/null +++ b/dataforge-meta/src/jsMain/kotlin/space/kscience/dataforge/misc/castJs.kt @@ -0,0 +1,5 @@ +package space.kscience.dataforge.misc +import kotlin.js.unsafeCast as unsafeCastJs + +@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") +public actual inline fun Any?.unsafeCast(): T = this.unsafeCastJs() \ No newline at end of file diff --git a/dataforge-meta/src/jvmMain/kotlin/space/kscience/dataforge/misc/castJvm.kt b/dataforge-meta/src/jvmMain/kotlin/space/kscience/dataforge/misc/castJvm.kt new file mode 100644 index 00000000..27d399fe --- /dev/null +++ b/dataforge-meta/src/jvmMain/kotlin/space/kscience/dataforge/misc/castJvm.kt @@ -0,0 +1,4 @@ +package space.kscience.dataforge.misc + +@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") +public actual inline fun Any?.unsafeCast(): T = this as T \ No newline at end of file diff --git a/dataforge-meta/src/nativeMain/kotlin/space/kscience/dataforge/misc/castNative.kt b/dataforge-meta/src/nativeMain/kotlin/space/kscience/dataforge/misc/castNative.kt new file mode 100644 index 00000000..27d399fe --- /dev/null +++ b/dataforge-meta/src/nativeMain/kotlin/space/kscience/dataforge/misc/castNative.kt @@ -0,0 +1,4 @@ +package space.kscience.dataforge.misc + +@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") +public actual inline fun Any?.unsafeCast(): T = this as T \ No newline at end of file