- no caching on stored delegates, fix problens with memory storage connections
+ optStored now properly load/store only non-null values * possible concurrent modification in KVStorage.clear fixed
This commit is contained in:
1 parent
2eb38e27ed
commit
d29bf960aa
4 files changed
+86
-42
No files matched your search
@@ -1,11 +1,10 @@
|
||||
package net.sergeych.bintools
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.serializer
|
||||
import net.sergeych.bipack.BipackDecoder
|
||||
import net.sergeych.bipack.BipackEncoder
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
|
||||
/**
|
||||
@@ -43,7 +42,7 @@ interface KVStorage {
|
||||
* Default implementation uses [keys]. You may override it for performance
|
||||
*/
|
||||
fun clear() {
|
||||
for (k in keys) this[k] = null
|
||||
for (k in keys.toList()) this[k] = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,46 +92,50 @@ inline fun <reified T:Any>KVStorage.read(key: String): T? =
|
||||
@Suppress("unused")
|
||||
inline fun <reified T:Any>KVStorage.load(key: String): T? = read(key)
|
||||
|
||||
inline operator fun <reified T> KVStorage.invoke(defaultValue: T,overrideName: String? = null) =
|
||||
KVStorageDelegate<T>(this, typeOf<T>(), defaultValue, overrideName)
|
||||
inline operator fun <reified T: Any> KVStorage.invoke(defaultValue: T,overrideName: String? = null) =
|
||||
KVStorageDelegate(this, serializer<T>(), defaultValue, overrideName)
|
||||
|
||||
inline fun <reified T> KVStorage.stored(defaultValue: T, overrideName: String? = null) =
|
||||
KVStorageDelegate<T>(this, typeOf<T>(), defaultValue, overrideName)
|
||||
inline fun <reified T: Any> KVStorage.stored(defaultValue: T, overrideName: String? = null) =
|
||||
KVStorageDelegate(this, serializer<T>(), defaultValue, overrideName)
|
||||
|
||||
inline fun <reified T> KVStorage.optStored(overrideName: String? = null) =
|
||||
KVStorageDelegate<T?>(this, typeOf<T?>(), null, overrideName)
|
||||
inline fun <reified T: Any> KVStorage.optStored(overrideName: String? = null) =
|
||||
KVStorageOptDelegate<T>(this, serializer<T>(),overrideName)
|
||||
|
||||
class KVStorageDelegate<T>(
|
||||
class KVStorageDelegate<T: Any>(
|
||||
private val storage: KVStorage,
|
||||
type: KType,
|
||||
private val serializer: KSerializer<T>,
|
||||
private val defaultValue: T,
|
||||
private val overrideName: String? = null,
|
||||
) {
|
||||
|
||||
private fun name(property: KProperty<*>): String = overrideName ?: property.name
|
||||
|
||||
private var cachedValue: T = defaultValue
|
||||
private var cacheReady = false
|
||||
private val serializer = serializer(type)
|
||||
operator fun getValue(thisRef: Any?, property: KProperty<*>): T =
|
||||
storage.get(name(property))?.let { BipackDecoder.decode(serializer, it) }
|
||||
?: defaultValue
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
||||
if (cacheReady) return cachedValue
|
||||
val data = storage.get(name(property))
|
||||
if (data == null)
|
||||
cachedValue = defaultValue
|
||||
else
|
||||
cachedValue = BipackDecoder.decode(data.toDataSource(), serializer) as T
|
||||
cacheReady = true
|
||||
return cachedValue
|
||||
}
|
||||
|
||||
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
|
||||
// if (!cacheReady || value != cachedValue) {
|
||||
cachedValue = value
|
||||
cacheReady = true
|
||||
storage[name(property)] = BipackEncoder.encode(serializer, value)
|
||||
}
|
||||
}
|
||||
|
||||
class KVStorageOptDelegate<T: Any>(
|
||||
private val storage: KVStorage,
|
||||
private val serializer: KSerializer<T>,
|
||||
private val overrideName: String? = null,
|
||||
) {
|
||||
private fun name(property: KProperty<*>): String = overrideName ?: property.name
|
||||
|
||||
operator fun getValue(thisRef: Any?, property: KProperty<*>): T? =
|
||||
storage.get(name(property))?.let{
|
||||
BipackDecoder.decode(serializer, it)
|
||||
}
|
||||
|
||||
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
|
||||
if (value == null)
|
||||
storage.delete(name(property))
|
||||
else
|
||||
storage[name(property)] = BipackEncoder.encode(serializer, value)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user