From e62f46b4781860b49d8424d995fccba644cb58ae Mon Sep 17 00:00:00 2001 From: Matthew Nelson Date: Thu, 18 Jan 2024 08:02:37 -0500 Subject: [PATCH 1/2] Add immutable collections library --- README.md | 3 +++ gradle/libs.versions.toml | 6 +++++- library/driver/build.gradle.kts | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 69af95d..aa2feee 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ [![badge-sqlite]][url-sqlite] [![badge-coroutines]][url-coroutines] [![badge-encoding]][url-encoding] +[![badge-immutable]][url-immutable] [![badge-sqldelight]][url-sqldelight] [![badge-sqlitemc]][url-sqlitemc] [![badge-sqliter]][url-sqliter] @@ -404,6 +405,7 @@ I'm guessing this is not really a factor on iOS." [badge-kotlin]: https://img.shields.io/badge/kotlin-1.9.21-blue.svg?logo=kotlin [badge-coroutines]: https://img.shields.io/badge/coroutines-1.7.3-blue.svg?logo=kotlin [badge-encoding]: https://img.shields.io/badge/encoding-2.1.0-blue.svg?style=flat +[badge-immutable]: https://img.shields.io/badge/immutable-0.1.0--alpha01-blue.svg?style=flat [badge-sqldelight]: https://img.shields.io/badge/SQLDelight-2.0.0-blue.svg?style=flat [badge-sqlite]: https://img.shields.io/badge/SQLite3-3.43.2-blue.svg?style=flat [badge-sqlitemc]: https://img.shields.io/badge/SQLite3MultipleCiphers-1.7.2-blue.svg?style=flat @@ -433,6 +435,7 @@ I'm guessing this is not really a factor on iOS." [url-kotlin]: https://kotlinlang.org [url-coroutines]: https://github.com/Kotlin/kotlinx.coroutines [url-encoding]: https://github.com/05nelsonm/encoding +[url-immutable]: https://github.com/05nelsonm/immutable [url-sqldelight]: https://github.com/cashapp/sqldelight [url-sqlite]: https://sqlite.org [url-sqlitemc]: https://github.com/utelle/SQLite3MultipleCiphers diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f0bf3c1..8e99f4c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,10 +9,12 @@ gradle-android = "8.1.4" gradle-binary-compat = "0.13.2" gradle-build-config = "4.1.2" gradle-cklib = "0.3.0" -gradle-kmp-configuration = "0.1.5" +gradle-kmp-configuration = "0.1.7" gradle-kotlin = "1.9.21" gradle-maven-publish = "0.25.3" +immutable = "0.1.0-alpha01" + kotlinx-coroutines = "1.7.3" okio = "3.5.0" @@ -36,6 +38,8 @@ gradle-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version. gradle-maven-publish = { module = "com.vanniktech:gradle-maven-publish-plugin", version.ref = "gradle-maven-publish" } gradle-sql-delight = { module = "app.cash.sqldelight:gradle-plugin", version.ref = "sql-delight" } +immutable-collections = { module = "io.matthewnelson.immutable:collections", version.ref = "immutable" } + kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" } diff --git a/library/driver/build.gradle.kts b/library/driver/build.gradle.kts index a97293d..81d5914 100644 --- a/library/driver/build.gradle.kts +++ b/library/driver/build.gradle.kts @@ -84,6 +84,7 @@ kmpConfiguration { dependencies { api(libs.sql.delight.runtime) implementation(libs.encoding.base16) + implementation(libs.immutable.collections) implementation(libs.kotlinx.coroutines.core) } } From 93468b614ed57436f48c3da7f8bb4adeca5eb2b2 Mon Sep 17 00:00:00 2001 From: Matthew Nelson Date: Thu, 18 Jan 2024 08:08:06 -0500 Subject: [PATCH 2/2] Use immutable collections for all list/set/map --- library/driver/api/android/driver.api | 2 +- library/driver/api/jvm/driver.api | 2 +- .../sqlite/mc/driver/config/FactoryConfig.kt | 5 ++- .../sqlite/mc/driver/config/MCPragma.kt | 39 ++++++++++--------- .../sqlite/mc/driver/config/PragmaConfig.kt | 22 ++--------- .../encryption/EncryptionMigrationConfig.kt | 3 +- .../sqlite/mc/driver/PlatformDriver.kt | 4 +- .../sqlite/mc/driver/PlatformDriver.kt | 4 +- 8 files changed, 35 insertions(+), 46 deletions(-) diff --git a/library/driver/api/android/driver.api b/library/driver/api/android/driver.api index b02bdb5..c552f0d 100644 --- a/library/driver/api/android/driver.api +++ b/library/driver/api/android/driver.api @@ -75,7 +75,7 @@ public final class io/toxicity/sqlite/mc/driver/config/FactoryConfig { public final field platformConfig Lio/toxicity/sqlite/mc/driver/config/PlatformConfig; public final field pragmaConfig Lio/toxicity/sqlite/mc/driver/config/PragmaConfig; public final field schema Lapp/cash/sqldelight/db/SqlSchema; - public synthetic fun (Ljava/lang/String;Lapp/cash/sqldelight/db/SqlSchema;Lio/toxicity/sqlite/mc/driver/config/FilesystemConfig;Lio/toxicity/sqlite/mc/driver/config/PlatformConfig;Lio/toxicity/sqlite/mc/driver/config/PragmaConfig;Lkotlinx/coroutines/CoroutineDispatcher;[Lapp/cash/sqldelight/db/AfterVersion;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Lapp/cash/sqldelight/db/SqlSchema;Lio/toxicity/sqlite/mc/driver/config/FilesystemConfig;Lio/toxicity/sqlite/mc/driver/config/PlatformConfig;Lio/toxicity/sqlite/mc/driver/config/PragmaConfig;Lkotlinx/coroutines/CoroutineDispatcher;Ljava/util/List;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V } public final class io/toxicity/sqlite/mc/driver/config/FactoryConfig$Builder { diff --git a/library/driver/api/jvm/driver.api b/library/driver/api/jvm/driver.api index 5870f0e..aa17358 100644 --- a/library/driver/api/jvm/driver.api +++ b/library/driver/api/jvm/driver.api @@ -71,7 +71,7 @@ public final class io/toxicity/sqlite/mc/driver/config/FactoryConfig { public final field platformConfig Lio/toxicity/sqlite/mc/driver/config/PlatformConfig; public final field pragmaConfig Lio/toxicity/sqlite/mc/driver/config/PragmaConfig; public final field schema Lapp/cash/sqldelight/db/SqlSchema; - public synthetic fun (Ljava/lang/String;Lapp/cash/sqldelight/db/SqlSchema;Lio/toxicity/sqlite/mc/driver/config/FilesystemConfig;Lio/toxicity/sqlite/mc/driver/config/PlatformConfig;Lio/toxicity/sqlite/mc/driver/config/PragmaConfig;Lkotlinx/coroutines/CoroutineDispatcher;[Lapp/cash/sqldelight/db/AfterVersion;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Lapp/cash/sqldelight/db/SqlSchema;Lio/toxicity/sqlite/mc/driver/config/FilesystemConfig;Lio/toxicity/sqlite/mc/driver/config/PlatformConfig;Lio/toxicity/sqlite/mc/driver/config/PragmaConfig;Lkotlinx/coroutines/CoroutineDispatcher;Ljava/util/List;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V } public final class io/toxicity/sqlite/mc/driver/config/FactoryConfig$Builder { diff --git a/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/FactoryConfig.kt b/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/FactoryConfig.kt index 073e41c..5c99d84 100644 --- a/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/FactoryConfig.kt +++ b/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/FactoryConfig.kt @@ -20,6 +20,7 @@ import app.cash.sqldelight.db.QueryResult import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.db.SqlSchema import app.cash.sqldelight.logs.LogSqliteDriver +import io.matthewnelson.immutable.collections.toImmutableList import io.toxicity.sqlite.mc.driver.MCConfigDsl import io.toxicity.sqlite.mc.driver.SQLiteMCDriver import kotlinx.coroutines.CoroutineDispatcher @@ -50,7 +51,7 @@ public class FactoryConfig private constructor( @JvmSynthetic internal val dispatcher: CoroutineDispatcher, @JvmSynthetic - internal val afterVersions: Array, + internal val afterVersions: List, @JvmSynthetic internal val logger: ((String) -> Unit)?, ) { @@ -226,7 +227,7 @@ public class FactoryConfig private constructor( dispatcher } }, - afterVersions = afterVersions.toTypedArray(), + afterVersions = afterVersions.toImmutableList(), logger = logger.toRedactedLoggerOrNull(redactLogs, dbName), ) } diff --git a/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/MCPragma.kt b/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/MCPragma.kt index e4de0c3..d8287ac 100644 --- a/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/MCPragma.kt +++ b/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/MCPragma.kt @@ -18,6 +18,9 @@ package io.toxicity.sqlite.mc.driver.config import app.cash.sqldelight.db.SqlCursor +import io.matthewnelson.immutable.collections.immutableSetOf +import io.matthewnelson.immutable.collections.toImmutableList +import io.matthewnelson.immutable.collections.toImmutableSet import io.toxicity.sqlite.mc.driver.MCConfigDsl import io.toxicity.sqlite.mc.driver.config.encryption.* import io.toxicity.sqlite.mc.driver.internal.ext.buildMCConfigSQL @@ -130,23 +133,23 @@ public abstract class MCPragma private constructor( @JvmStatic @get:JvmSynthetic internal val ALL: Set> by lazy { - buildSet(capacity = 16) { - add(CIPHER) - add(HMAC_CHECK) - add(MC_LEGACY_WAL) - add(LEGACY) - add(LEGACY_PAGE_SIZE) - add(KDF_ITER) - add(FAST_KDF_ITER) - add(HMAC_USE) - add(HMAC_PNGO) - add(HMAC_SALT_MASK) - add(KDF_ALGORITHM) - add(HMAC_ALGORITHM) - add(PLAIN_TEXT_HEADER_SIZE) - add(KEY) - add(RE_KEY) - } + immutableSetOf( + CIPHER, + HMAC_CHECK, + MC_LEGACY_WAL, + LEGACY, + LEGACY_PAGE_SIZE, + KDF_ITER, + FAST_KDF_ITER, + HMAC_USE, + HMAC_PNGO, + HMAC_SALT_MASK, + KDF_ALGORITHM, + HMAC_ALGORITHM, + PLAIN_TEXT_HEADER_SIZE, + KEY, + RE_KEY, + ) } private val TransformAny: Transformer = Transformer { it.toString() } @@ -258,5 +261,5 @@ internal fun MCPragmas.toMCSQLStatements(): List { } addAll(rekeyNonTransient) - } + }.toImmutableList() } diff --git a/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/PragmaConfig.kt b/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/PragmaConfig.kt index ca3de38..e531577 100644 --- a/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/PragmaConfig.kt +++ b/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/PragmaConfig.kt @@ -15,6 +15,7 @@ **/ package io.toxicity.sqlite.mc.driver.config +import io.matthewnelson.immutable.collections.toImmutableMap import io.toxicity.sqlite.mc.driver.EphemeralOpt import io.toxicity.sqlite.mc.driver.MCConfigDsl import io.toxicity.sqlite.mc.driver.SQLiteMCDriver @@ -157,8 +158,8 @@ public class PragmaConfig private constructor( } return PragmaConfig( - ephemeral = ImmutablePragma(ephemeral), - filesystem = ImmutablePragma(filesystem), + ephemeral = ephemeral.toImmutableMap(), + filesystem = filesystem.toImmutableMap(), ) } @@ -226,20 +227,3 @@ public class PragmaConfig private constructor( } } } - -private class ImmutablePragma( - map: MutableMap, -): Map { - - private val delegate = map.toMap() - - override val entries: Set> get() = delegate.entries - override val keys: Set get() = delegate.keys - override val size: Int get() = delegate.size - override val values: Collection get() = delegate.values - - override fun isEmpty(): Boolean = delegate.isEmpty() - override operator fun get(key: String): String? = delegate[key] - override fun containsValue(value: String): Boolean = delegate.containsValue(value) - override fun containsKey(key: String): Boolean = delegate.containsKey(key) -} diff --git a/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/encryption/EncryptionMigrationConfig.kt b/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/encryption/EncryptionMigrationConfig.kt index 89fb9ab..94a7bbb 100644 --- a/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/encryption/EncryptionMigrationConfig.kt +++ b/library/driver/src/commonMain/kotlin/io/toxicity/sqlite/mc/driver/config/encryption/EncryptionMigrationConfig.kt @@ -15,6 +15,7 @@ **/ package io.toxicity.sqlite.mc.driver.config.encryption +import io.matthewnelson.immutable.collections.toImmutableSet import io.toxicity.sqlite.mc.driver.MCConfigDsl import io.toxicity.sqlite.mc.driver.SQLiteMCDriver import io.toxicity.sqlite.mc.driver.config.FilesystemConfig @@ -238,7 +239,7 @@ public class EncryptionMigrationConfig private constructor( @JvmSynthetic internal fun build(): EncryptionMigrationConfig? { - val set = migrations.toSet() + val set = migrations.toImmutableSet() if (set.isEmpty()) return null return EncryptionMigrationConfig(set) } diff --git a/library/driver/src/jvmAndroidMain/kotlin/io/toxicity/sqlite/mc/driver/PlatformDriver.kt b/library/driver/src/jvmAndroidMain/kotlin/io/toxicity/sqlite/mc/driver/PlatformDriver.kt index 2979b88..59fe3ea 100644 --- a/library/driver/src/jvmAndroidMain/kotlin/io/toxicity/sqlite/mc/driver/PlatformDriver.kt +++ b/library/driver/src/jvmAndroidMain/kotlin/io/toxicity/sqlite/mc/driver/PlatformDriver.kt @@ -129,7 +129,7 @@ public actual sealed class PlatformDriver actual constructor(private val args: A properties = properties, schema = schema, migrateEmptySchema = platformConfig.migrateEmptySchema, - callbacks = afterVersions, + callbacks = afterVersions.toTypedArray(), ) } catch (t: Throwable) { properties.clear() @@ -160,7 +160,7 @@ public actual sealed class PlatformDriver actual constructor(private val args: A properties = properties, schema = schema, migrateEmptySchema = platformConfig.migrateEmptySchema, - callbacks = afterVersions, + callbacks = afterVersions.toTypedArray(), ) } catch (t: Throwable) { if (t is IllegalStateException) throw t diff --git a/library/driver/src/nativeMain/kotlin/io/toxicity/sqlite/mc/driver/PlatformDriver.kt b/library/driver/src/nativeMain/kotlin/io/toxicity/sqlite/mc/driver/PlatformDriver.kt index 98b4b4f..e8a9dd8 100644 --- a/library/driver/src/nativeMain/kotlin/io/toxicity/sqlite/mc/driver/PlatformDriver.kt +++ b/library/driver/src/nativeMain/kotlin/io/toxicity/sqlite/mc/driver/PlatformDriver.kt @@ -278,10 +278,10 @@ private fun SqlSchema>.create(): (DatabaseConnection) -> } private fun SqlSchema>.upgrade( - afterVersions: Array + afterVersions: List ): (DatabaseConnection, Int, Int) -> Unit = { connection, oldVersion, newVersion -> wrapConnection(connection) { - migrate(it, oldVersion.toLong(), newVersion.toLong(), callbacks = afterVersions) + migrate(it, oldVersion.toLong(), newVersion.toLong(), callbacks = afterVersions.toTypedArray()) } }