All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.dev.kord.cache.map.MapLikeCollection.kt Maven / Gradle / Ivy

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