Skip to content

Commit

Permalink
Added mutation types
Browse files Browse the repository at this point in the history
  • Loading branch information
y9san9 committed Jun 7, 2021
2 parents e94f805 + 4317335 commit 03287a8
Show file tree
Hide file tree
Showing 13 changed files with 372 additions and 14 deletions.
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/AppInfo.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
object AppInfo {
const val PACKAGE = "fun.kotlingang.kds"
const val VERSION = "5.2.0"
const val VERSION = "5.2.1"
const val NAME = "Kotlin Data Storage"
const val DESCRIPTION = "Multiplatform Coroutine-Based Kotlin Library for storing data via kotlinx.serialization"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package `fun`.kotlingang.kds.annotation


@RequiresOptIn (
message = "This API is unstable yet, probably you can see why in the kdoc",
level = RequiresOptIn.Level.WARNING
)
public annotation class ExperimentalKDSApi
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package `fun`.kotlingang.kds.delegate

import kotlin.reflect.KProperty


public fun interface DelegateProvider<in TReceiver, out TDelegate> {
public operator fun provideDelegate(thisRef: TReceiver, property: KProperty<*>): TDelegate
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package `fun`.kotlingang.kds.delegate

import `fun`.kotlingang.kds.annotation.ExperimentalKDSApi
import `fun`.kotlingang.kds.annotation.UnsafeKType
import `fun`.kotlingang.kds.mutate.StorageList
import `fun`.kotlingang.kds.storage.KTypeDataStorage
import kotlin.reflect.typeOf


/**
* @see [StorageList]
*/
@ExperimentalKDSApi
@OptIn(ExperimentalStdlibApi::class, UnsafeKType::class)
public inline fun <reified T> KTypeDataStorage.storageList (
list: MutableList<T>
): DelegateProvider<Any?, KDSProperty<MutableList<T>>> =
DelegateProvider { _, property ->
property {
StorageList(property.name, storage = this, list, typeOf<MutableList<T>>())
}
}

/**
* @see [StorageList]
*/
@ExperimentalKDSApi
public inline fun <reified T> KTypeDataStorage.storageList (
vararg elements: T
): DelegateProvider<Any?, KDSProperty<MutableList<T>>> = storageList(mutableListOf(*elements))

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package `fun`.kotlingang.kds.delegate

import `fun`.kotlingang.kds.annotation.ExperimentalKDSApi
import `fun`.kotlingang.kds.annotation.UnsafeKType
import `fun`.kotlingang.kds.mutate.StorageMap
import `fun`.kotlingang.kds.storage.KTypeDataStorage
import kotlin.reflect.typeOf


/**
* @see [StorageMap]
*/
@ExperimentalKDSApi
@OptIn(ExperimentalStdlibApi::class, UnsafeKType::class)
public inline fun <reified K, reified V> KTypeDataStorage.storageMap (
map: MutableMap<K, V>
): DelegateProvider<Any?, KDSProperty<MutableMap<K, V>>> =
DelegateProvider { _, property ->
property {
StorageMap(property.name, storage = this, map, typeOf<MutableMap<K, V>>())
}
}

/**
* @see [StorageMap]
*/
@ExperimentalKDSApi
public inline fun <reified K, reified V> KTypeDataStorage.storageMap (
vararg pairs: Pair<K, V>
): DelegateProvider<Any?, KDSProperty<MutableMap<K, V>>> = storageMap(mutableMapOf(*pairs))
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package `fun`.kotlingang.kds.delegate

import `fun`.kotlingang.kds.annotation.ExperimentalKDSApi
import `fun`.kotlingang.kds.annotation.UnsafeKType
import `fun`.kotlingang.kds.mutate.StorageSet
import `fun`.kotlingang.kds.storage.KTypeDataStorage
import kotlin.reflect.typeOf


/**
* @see [StorageSet]
*/
@ExperimentalKDSApi
@OptIn(ExperimentalStdlibApi::class, UnsafeKType::class)
public inline fun <reified T> KTypeDataStorage.storageSet (
map: MutableSet<T>
): DelegateProvider<Any?, KDSProperty<MutableSet<T>>> =
DelegateProvider { _, property ->
property {
StorageSet(property.name, storage = this, map, typeOf<MutableSet<T>>())
}
}

/**
* @see [StorageSet]
*/
@ExperimentalKDSApi
public inline fun <reified T> KTypeDataStorage.storageSet (
vararg elements: T
): DelegateProvider<Any?, KDSProperty<MutableSet<T>>> = storageSet(mutableSetOf(*elements))

Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package `fun`.kotlingang.kds.mutate


internal class SavableList<T> (
private val listSource: MutableList<T>,
private val saveAction: SavableList<T>.() -> Unit
) : MutableList<T> by listSource {
private fun save() = saveAction()

override fun add(element: T): Boolean =
listSource.add(element).apply { save() }

override fun add(index: Int, element: T) {
listSource.add(index, element)
save()
}

override fun addAll(elements: Collection<T>): Boolean =
listSource.addAll(elements).apply { save() }

override fun addAll(index: Int, elements: Collection<T>): Boolean =
listSource.addAll(index, elements).apply { save() }

override fun clear() {
listSource.clear()
save()
}

private fun listIterator(iterator: MutableListIterator<T>) = object : MutableListIterator<T> by listIterator() {
override fun add(element: T) {
iterator.add(element)
save()
}
override fun remove() {
iterator.remove()
save()
}
override fun set(element: T) {
iterator.set(element)
save()
}
}

override fun listIterator(): MutableListIterator<T> =
listIterator(listSource.listIterator())

override fun listIterator(index: Int): MutableListIterator<T> =
listIterator(listSource.listIterator(index))

override fun remove(element: T): Boolean =
listSource.remove(element).apply { save() }

override fun removeAll(elements: Collection<T>): Boolean =
listSource.retainAll(elements).apply { save() }

override fun removeAt(index: Int): T =
listSource.removeAt(index).apply { save() }

override fun retainAll(elements: Collection<T>): Boolean =
listSource.retainAll(elements).apply { save() }

override fun set(index: Int, element: T): T =
listSource.set(index, element).apply { save() }
}
61 changes: 61 additions & 0 deletions core/src/commonMain/kotlin/fun/kotlingang/kds/mutate/SavableMap.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package `fun`.kotlingang.kds.mutate


internal class SavableMap<K, V> (
private val mapSource: MutableMap<K, V>,
private val saveAction: SavableMap<K, V>.() -> Unit
) : MutableMap<K, V> by mapSource {
override val entries: MutableSet<MutableMap.MutableEntry<K, V>>

init {
val set = SavableSet (
setSource = mapSource.entries,
saveAction = { saveAction() }
)
entries = object : MutableSet<MutableMap.MutableEntry<K, V>> by set {
override fun iterator(): MutableIterator<MutableMap.MutableEntry<K, V>> {
val iterator = set.iterator()

return object : MutableIterator<MutableMap.MutableEntry<K, V>> by iterator {
override fun next(): MutableMap.MutableEntry<K, V> {
val nextEntry = iterator.next()
return object : MutableMap.MutableEntry<K, V> by nextEntry {
override fun setValue(newValue: V): V = nextEntry.setValue(newValue).apply {
saveAction()
}
}
}
}
}
}
}

override val keys: MutableSet<K> =
object : MutableSet<K> by SavableSet (
setSource = mapSource.keys,
saveAction = { saveAction() }
) {}

override val values: MutableList<V> =
object : MutableList<V> by SavableList (
listSource = mapSource.values.toMutableList(),
saveAction = { saveAction() }
) {}

override fun clear() {
mapSource.clear()
saveAction()
}

override fun put(key: K, value: V): V? = mapSource.put(key, value).apply {
saveAction()
}

override fun putAll(from: Map<out K, V>): Unit = mapSource.putAll(from).let {
saveAction()
}

override fun remove(key: K): V? = mapSource.remove(key).apply {
saveAction()
}
}
43 changes: 43 additions & 0 deletions core/src/commonMain/kotlin/fun/kotlingang/kds/mutate/SavableSet.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package `fun`.kotlingang.kds.mutate


internal class SavableSet<T> (
private val setSource: MutableSet<T>,
private val saveAction: SavableSet<T>.() -> Unit
) : MutableSet<T> by setSource {
override fun add(element: T): Boolean = setSource.add(element).apply {
saveAction()
}

override fun addAll(elements: Collection<T>): Boolean = setSource.addAll(elements).apply {
saveAction()
}

override fun iterator(): MutableIterator<T> {
val iterator = setSource.iterator()

return object : MutableIterator<T> by iterator {
override fun remove() {
iterator.remove()
saveAction()
}
}
}

override fun clear() {
setSource.clear()
saveAction()
}

override fun remove(element: T): Boolean = setSource.remove(element).apply {
saveAction()
}

override fun removeAll(elements: Collection<T>): Boolean = setSource.removeAll(elements).apply {
saveAction()
}

override fun retainAll(elements: Collection<T>): Boolean = setSource.retainAll(elements).apply {
saveAction()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package `fun`.kotlingang.kds.mutate

import `fun`.kotlingang.kds.annotation.ExperimentalKDSApi
import `fun`.kotlingang.kds.annotation.RawSetterGetter
import `fun`.kotlingang.kds.annotation.UnsafeKType
import `fun`.kotlingang.kds.storage.KTypeDataStorage
import kotlin.reflect.KType


/**
* This API is experimental as [StorageMap]
* You can write your ideas to #16
* After some testing time we probably will understand should we
* keep this types in library or not
*/
@ExperimentalKDSApi
@OptIn(UnsafeKType::class, RawSetterGetter::class)
public class StorageList<T> @UnsafeKType constructor (
private val storageKey: String,
private val storage: KTypeDataStorage,
private val listSource: MutableList<T>,
private val listType: KType
) : MutableList<T> by SavableList(listSource, saveAction = {
storage.putWithKType(storageKey, listType, listSource)
})
25 changes: 25 additions & 0 deletions core/src/commonMain/kotlin/fun/kotlingang/kds/mutate/StorageMap.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package `fun`.kotlingang.kds.mutate

import `fun`.kotlingang.kds.annotation.ExperimentalKDSApi
import `fun`.kotlingang.kds.annotation.RawSetterGetter
import `fun`.kotlingang.kds.annotation.UnsafeKType
import `fun`.kotlingang.kds.storage.KTypeDataStorage
import kotlin.reflect.KType


/**
* This API is experimental since there are no ideas for clear implementation of it (exactly map)
* You can write your ideas to #16
* After some testing time we probably will understand should we
* keep this types in library or not
*/
@ExperimentalKDSApi
@OptIn(UnsafeKType::class, RawSetterGetter::class)
public class StorageMap<K, V> @UnsafeKType constructor (
private val storageKey: String,
private val storage: KTypeDataStorage,
private val mapSource: MutableMap<K, V>,
private val mapType: KType,
) : MutableMap<K, V> by SavableMap(mapSource, saveAction = {
storage.putWithKType(storageKey, mapType, mapSource)
})
24 changes: 24 additions & 0 deletions core/src/commonMain/kotlin/fun/kotlingang/kds/mutate/StorageSet.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package `fun`.kotlingang.kds.mutate

import `fun`.kotlingang.kds.annotation.ExperimentalKDSApi
import `fun`.kotlingang.kds.annotation.RawSetterGetter
import `fun`.kotlingang.kds.annotation.UnsafeKType
import `fun`.kotlingang.kds.storage.KTypeDataStorage
import kotlin.reflect.KType

/**
* This API is experimental as [StorageMap]
* You can write your ideas to #16
* After some testing time we probably will understand should we
* keep this types in library or not
*/
@ExperimentalKDSApi
@OptIn(UnsafeKType::class, RawSetterGetter::class)
public class StorageSet<T> @UnsafeKType constructor (
private val storageKey: String,
private val storage: KTypeDataStorage,
private val setSource: MutableSet<T>,
private val setType: KType
) : MutableSet<T> by SavableSet(setSource, saveAction = {
storage.putWithKType(storageKey, setType, setSource)
})
Loading

0 comments on commit 03287a8

Please sign in to comment.