commonMain.dev.kord.cache.map.MapLikeCollection.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cache-map-jvm Show documentation
Show all versions of cache-map-jvm Show documentation
Adaptable cache with query-like operations
The newest version!
package dev.kord.cache.map
import dev.kord.cache.api.ConcurrentHashMap
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flow
interface MapLikeCollection {
suspend fun get(key: KEY): VALUE?
suspend fun contains(key: KEY): Boolean = get(key) != null
suspend fun put(key: KEY, value: VALUE)
fun values(): Flow
suspend fun clear()
suspend fun remove(key: KEY)
fun getByKey(predicate: suspend (KEY) -> Boolean): Flow
fun getByValue(predicate: suspend (VALUE) -> Boolean): Flow
companion object {
private val empty = object : MapLikeCollection {
override suspend fun clear() {}
override suspend fun get(key: Any): Any? = null
override suspend fun put(key: Any, value: Any) {}
override suspend fun remove(key: Any) {}
override fun values(): Flow = emptyFlow()
override fun getByKey(predicate: suspend (Any) -> Boolean): Flow = emptyFlow()
override fun getByValue(predicate: suspend (Any) -> Boolean): Flow = emptyFlow()
}
/**
* Returns an empty immutable [MapLikeCollection].
* This collection will always return null and empty flows and ignores inserted valued.
*/
@Suppress("UNCHECKED_CAST")
fun none(): MapLikeCollection = empty as MapLikeCollection
/**
* Wraps the [map] in a [MapLikeCollection].
*/
fun concurrentHashMap(map: ConcurrentHashMap = ConcurrentHashMap()) = from(map)
/**
* Wraps the [map] in a [MapLikeCollection] that ignores inserted values.
*/
fun readOnly(map: Map) = object : MapLikeCollection {
override suspend fun clear() {}
override suspend fun get(key: K): V? = map[key]
override suspend fun put(key: K, value: V) {}
override suspend fun remove(key: K) {}
override fun values(): Flow = flow {
map.values.forEach { emit(it) }
}
override fun getByKey(predicate: suspend (K) -> Boolean): Flow = flow {
for ((key, value) in map.entries.toList()) if (predicate(key)) emit(value)
}
override fun getByValue(predicate: suspend (V) -> Boolean): Flow = flow {
for (value in map.values.toList()) if (predicate(value)) emit(value)
}
}
/**
* Wraps the [map] in a [MapLikeCollection], data will be copied on read to prevent modification exceptions.
*/
fun from(map: MutableMap) = object : MapLikeCollection {
override suspend fun get(key: KEY): VALUE? = map[key]
override suspend fun contains(key: KEY): Boolean = map.contains(key)
override suspend fun put(key: KEY, value: VALUE) {
map[key] = value
}
override fun values(): Flow = flow {
ArrayList(map.values).forEach { emit(it) }
}
override suspend fun clear() = map.clear()
override suspend fun remove(key: KEY) {
map.remove(key)
}
override fun getByKey(predicate: suspend (KEY) -> Boolean): Flow = flow {
for ((key, value) in map.entries.toList()) {
if (predicate(key)) {
emit(value)
}
}
}
override fun getByValue(predicate: suspend (VALUE) -> Boolean): Flow = flow {
for (value in map.values.toList()) {
if (predicate(value)) {
emit(value)
}
}
}
}
/**
* Wraps the [map] in a [MapLikeCollection], this assumes that the [map] can safely be accessed concurrently.
*/
fun fromThreadSafe(map: MutableMap) = object : MapLikeCollection {
override suspend fun get(key: KEY): VALUE? = map[key]
override suspend fun contains(key: KEY): Boolean =
map.contains(key)
override suspend fun put(key: KEY, value: VALUE) {
map[key] = value
}
override fun values(): Flow = flow {
map.values.forEach { emit(it) }
}
override suspend fun clear() = map.clear()
override suspend fun remove(key: KEY) {
map.remove(key)
}
override fun getByKey(predicate: suspend (KEY) -> Boolean): Flow = flow {
for ((key, value) in map.entries) {
if (predicate(key)) {
emit(value)
}
}
}
override fun getByValue(predicate: suspend (VALUE) -> Boolean): Flow = flow {
for (value in map.values) {
if (predicate(value)) {
emit(value)
}
}
}
}
}
}
/**
* Wraps the [map] in a [MapLikeCollection], this assumes that the [map] can safely be accessed concurrently if [concurrent] is `true`.
*/
fun MutableMap.toMapLike(concurrent: Boolean) = when (concurrent) {
true -> MapLikeCollection.fromThreadSafe(this)
false -> MapLikeCollection.from(this)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy