diff --git a/CHANGELOG.md b/CHANGELOG.md index 26804ca4732..e5806653b2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## 0.29.4 +* `Meta`: + * Inited + ## 0.29.3 * `Versions`: diff --git a/dokka/build.gradle b/dokka/build.gradle index e7e3d7a79e0..81501d643c6 100644 --- a/dokka/build.gradle +++ b/dokka/build.gradle @@ -91,7 +91,7 @@ kotlin { private List findSourcesWithName(String... approximateNames) { return parent.subprojects - .findAll { it != project && it.hasProperty("kotlin") } + .findAll { it != project && it.hasProperty("kotlin") && (it.name.contains("dokka") == false) } .collectMany { it.kotlin.sourceSets } .findAll { sourceSet -> approximateNames.any { nameToFilter -> diff --git a/meta/build.gradle b/meta/build.gradle new file mode 100644 index 00000000000..c7c28b5572b --- /dev/null +++ b/meta/build.gradle @@ -0,0 +1,12 @@ +plugins { + id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.serialization" + id "com.android.library" +} + +apply from: "$mppJvmJsWasmJsAndroidLinuxMingwLinuxArm64Project" + +kotlin { + sourceSets { + } +} diff --git a/meta/src/commonMain/kotlin/MetaContainer.kt b/meta/src/commonMain/kotlin/MetaContainer.kt new file mode 100644 index 00000000000..b46c0e972c7 --- /dev/null +++ b/meta/src/commonMain/kotlin/MetaContainer.kt @@ -0,0 +1,94 @@ +package dev.inmo.micro_utils.meta + +import kotlinx.serialization.Polymorphic +import kotlinx.serialization.Serializable + +/** + * A polymorphic container for storing heterogeneous key-value pairs with type-safe retrieval. + * Each key is bound to a specific type, enabling type-safe access to stored values. + * + * @property map The underlying map storing key-value pairs with polymorphic values. + */ +@Serializable +data class MetaContainer( + @MetaContainerRootMapWarning + val map: Map, @Polymorphic Any> +) { + /** + * A marker interface for type-safe keys in [MetaContainer]. + * + * @param T The type of value associated with this key. + */ + interface Key + + /** + * Retrieves a value from the container by its key. + * + * @param key The type-safe key to look up. + * @return The value associated with the key, or null if not present. + */ + @Suppress("UNCHECKED_CAST", "OPT_IN_USAGE") + operator fun get(key: Key): T? = map[key] as? T? + + /** + * Checks whether a value exists for the given key. + * + * @param key The type-safe key to check. + * @return true if the key exists and has a non-null value, false otherwise. + */ + operator fun contains(key: Key): Boolean = get(key) != null + + /** + * Builder for constructing [MetaContainer] instances with a fluent API. + */ + class Builder( + @MetaContainerRootMapWarning + private val map: MutableMap, Any> = mutableMapOf, Any>() + ) { + + + /** + * Puts a value associated with the given key into the builder. + * + * @param k The type-safe key. + * @param v The value to store. + */ + fun put(k: Key, v: T) { + map[k] = v + } + + /** + * Retrieves a value from the builder by its key. + * + * @param key The type-safe key to look up. + * @return The value associated with the key, or null if not present. + */ + @Suppress("UNCHECKED_CAST") + operator fun get(key: Key): T? = map[key] as T? + + /** + * Checks whether a value exists for the given key in the builder. + * + * @param key The type-safe key to check. + * @return true if the key exists and has a non-null value, false otherwise. + */ + operator fun contains(key: Key): Boolean = get(key) != null + + /** + * Builds and returns the immutable [MetaContainer] instance. + * + * @return A new [MetaContainer] with the accumulated key-value pairs. + */ + fun build(): MetaContainer = MetaContainer(map.toMap()) + } + + companion object { + /** + * An empty [MetaContainer] instance with no entries. + */ + val EMPTY = MetaContainer(emptyMap()) + } +} + + + diff --git a/meta/src/commonMain/kotlin/MetaContainerRootMapWarning.kt b/meta/src/commonMain/kotlin/MetaContainerRootMapWarning.kt new file mode 100644 index 00000000000..750cc0d8e8c --- /dev/null +++ b/meta/src/commonMain/kotlin/MetaContainerRootMapWarning.kt @@ -0,0 +1,17 @@ +package dev.inmo.micro_utils.meta + +/** + * Marks the direct use of [MetaContainer.map] as requiring explicit opt-in. + * + * This annotation warns against direct manipulation of the internal map without using + * the type-safe accessors, which could break type safety guarantees. + */ +@RequiresOptIn( + "Do not use this directly without any special reason", + RequiresOptIn.Level.WARNING +) +@Target( + AnnotationTarget.FIELD, +) +@Retention(AnnotationRetention.BINARY) +annotation class MetaContainerRootMapWarning diff --git a/meta/src/commonMain/kotlin/buildMetaContainer.kt b/meta/src/commonMain/kotlin/buildMetaContainer.kt new file mode 100644 index 00000000000..7b1d42ddfaa --- /dev/null +++ b/meta/src/commonMain/kotlin/buildMetaContainer.kt @@ -0,0 +1,13 @@ +package dev.inmo.micro_utils.meta + +/** + * DSL builder function for creating a [MetaContainer] with a lambda block. + * + * @param block A lambda with receiver ([MetaContainer.Builder]) to configure the container. + * @return A new [MetaContainer] instance built from the DSL block. + */ +fun buildMetaContainer(block: MetaContainer.Builder.() -> Unit): MetaContainer { + val builder = MetaContainer.Builder() + builder.block() + return builder.build() +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 99d4168788a..908cffc4eae 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,7 @@ rootProject.name='micro_utils' String[] includes = [ + ":meta", ":common", ":common:compose", ":transactions",