Thanks to visit codestin.com
Credit goes to github.com

Skip to content
134 changes: 134 additions & 0 deletions api/api/api.api
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,137 @@ public final class dev/kord/cache/api/meta/TypeStatisticsLogger {
public final fun logQuery ()V
}

public final class dev/kord/cache/api/observables/BasicRelation : dev/kord/cache/api/observables/Relation {
public fun <init> ()V
public fun remove (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun to (Ldev/kord/cache/api/observables/Cache;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public abstract interface class dev/kord/cache/api/observables/Cache {
public abstract fun filter (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun firstOrNull (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun get (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun relatesTo (Ldev/kord/cache/api/observables/Cache;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun remove (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun removeAll (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun removeAny (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun set (Ljava/lang/Object;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class dev/kord/cache/api/observables/ConcurrentCache : dev/kord/cache/api/observables/Cache {
public fun <init> (Ldev/kord/cache/api/observables/Relation;)V
public fun filter (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun firstOrNull (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun get (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun getRelation ()Ldev/kord/cache/api/observables/Relation;
public fun relatesTo (Ldev/kord/cache/api/observables/Cache;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun remove (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun removeAll (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun removeAny (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun set (Ljava/lang/Object;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public abstract interface class dev/kord/cache/api/observables/DataCache {
public abstract fun firstOrNull (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun get (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun getAll (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun put (Ljava/lang/Object;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun relatesTo (Ldev/kord/cache/api/observables/DataCache;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun remove (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun removeAll (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun removeIf (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public abstract interface class dev/kord/cache/api/observables/EntryCache {
public abstract fun asMap (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun firstOrNull (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun get (Ldev/kord/cache/api/observables/Index;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun put (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun relatesTo (Ldev/kord/cache/api/observables/EntryCache;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun remove (Ldev/kord/cache/api/observables/Index;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun removeAll (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun removeIf (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public abstract interface class dev/kord/cache/api/observables/Index : java/lang/Comparable {
public abstract fun hashCode ()I
}

public final class dev/kord/cache/api/observables/IndexCache : dev/kord/cache/api/observables/EntryCache {
public fun <init> (Ldev/kord/cache/api/observables/Relation;Lkotlin/jvm/functions/Function1;)V
public fun asMap (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun firstOrNull (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun get (Ldev/kord/cache/api/observables/Index;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun getIndexFactory ()Lkotlin/jvm/functions/Function1;
public final fun getRelation ()Ldev/kord/cache/api/observables/Relation;
public fun put (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun relatesTo (Ldev/kord/cache/api/observables/EntryCache;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun remove (Ldev/kord/cache/api/observables/Index;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun removeAll (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun removeIf (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public abstract interface class dev/kord/cache/api/observables/IndexFactory {
public abstract fun createIndexFor (Ljava/lang/Object;)Ldev/kord/cache/api/observables/Index;
}

public final class dev/kord/cache/api/observables/MemberData {
public fun <init> (II)V
public final fun component1 ()I
public final fun component2 ()I
public final fun copy (II)Ldev/kord/cache/api/observables/MemberData;
public static synthetic fun copy$default (Ldev/kord/cache/api/observables/MemberData;IIILjava/lang/Object;)Ldev/kord/cache/api/observables/MemberData;
public fun equals (Ljava/lang/Object;)Z
public final fun getGuildId ()I
public final fun getUserId ()I
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class dev/kord/cache/api/observables/MemberDataIndexFactory : dev/kord/cache/api/observables/IndexFactory {
public static final field INSTANCE Ldev/kord/cache/api/observables/MemberDataIndexFactory;
public fun createIndexFor (Ldev/kord/cache/api/observables/MemberData;)Ldev/kord/cache/api/observables/Index;
public synthetic fun createIndexFor (Ljava/lang/Object;)Ldev/kord/cache/api/observables/Index;
}

public abstract interface class dev/kord/cache/api/observables/Relation {
public abstract fun remove (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun to (Ldev/kord/cache/api/observables/Cache;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class dev/kord/cache/api/observables/SnowflakeSetIndex : dev/kord/cache/api/observables/Index {
public fun <init> (Ljava/util/Set;)V
public fun compareTo (Ldev/kord/cache/api/observables/Index;)I
public synthetic fun compareTo (Ljava/lang/Object;)I
public final fun getSnowflakes ()Ljava/util/Set;
public fun hashCode ()I
}

public final class dev/kord/cache/api/observables/TestKt {
public static final fun main (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun main ([Ljava/lang/String;)V
}

public abstract interface class dev/kord/cache/api/observables/TypedCache {
public abstract fun getType (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun putCache (Ldev/kord/cache/api/observables/EntryCache;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun toSet (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class dev/kord/cache/api/observables/UserData {
public fun <init> (I)V
public final fun component1 ()I
public final fun copy (I)Ldev/kord/cache/api/observables/UserData;
public static synthetic fun copy$default (Ldev/kord/cache/api/observables/UserData;IILjava/lang/Object;)Ldev/kord/cache/api/observables/UserData;
public fun equals (Ljava/lang/Object;)Z
public final fun getUserId ()I
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class dev/kord/cache/api/observables/UserIndexFactory : dev/kord/cache/api/observables/IndexFactory {
public static final field INSTANCE Ldev/kord/cache/api/observables/UserIndexFactory;
public fun createIndexFor (Ldev/kord/cache/api/observables/UserData;)Ldev/kord/cache/api/observables/Index;
public synthetic fun createIndexFor (Ljava/lang/Object;)Ldev/kord/cache/api/observables/Index;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package dev.kord.cache.api.observables

class BasicRelation<T: Any> : Relation<T> {
private val relations = mutableSetOf<RelationHandler<T, Any>>()
private val caches = mutableSetOf<Cache<*, *>>()

override suspend fun remove(value: T) {
relations.onEach { relatesTo ->
caches.onEach { other -> other.removeAny { friend -> relatesTo(value, friend) } }
}
}

override suspend fun <R : Any> to(cache: Cache<*, R>, handler: RelationHandler<T, R>) {
caches.add(cache)
relations.add(safe(handler))
}

private fun <R: Any> safe(relationHandler: RelationHandler<T, R>): RelationHandler<T, Any> {
return obj@{ value: T, friend: Any ->
@Suppress("UNCHECKED_CAST")
val safeCast = friend as? R
safeCast != null && relationHandler(value, safeCast)
}
}
}
59 changes: 59 additions & 0 deletions api/src/commonMain/kotlin/dev/kord/cache/api/observables/Cache.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package dev.kord.cache.api.observables

import kotlinx.coroutines.flow.Flow

/**
* A cache for a map of entries where each [Value] is associated with a unique [Key].
* */
interface Cache<Key : Any, Value : Any> {

/**
* Returns the value associated with the given [key] in the cache, or null if no such entry exists.
*/
suspend fun get(key: Key): Value?

/**
* Removes the entry associated with the given [key] from the cache, if it exists.
*/
suspend fun remove(key: Key)

/**
* Filters [Value]s by the given [predicate]
* Returns a lazy [Flow] of [Value]s
*/
suspend fun filter(predicate: (Value) -> Boolean): Sequence<Value>

/**
* Sets the [value] into the cache associated with a [key].
* @param key The key to associate the [value] with.
* @param value The value to be cached.
*/
suspend fun set(key: Key, value: Value)

/**
* Returns the first value that satisfies the given [predicate] function, or null if none is found.
* @param predicate A function that takes a [Value] and returns a boolean.
* @return The first value that satisfies the [predicate] function, or null if none is found.
*/
public suspend fun firstOrNull(predicate: (Value) -> Boolean): Value?

/**
* Removes any entry in the cache which matches the given [predicate].
* @param predicate The predicate to match each [Value] against.
*/
public suspend fun removeAny(predicate: (Value) -> Boolean)

/**
* Removes all entries in the cache.
*/
public suspend fun removeAll()

/**
* Adds an observer cache to this cache. Whenever a value is removed from this cache, the
* observer cache will also remove any values that are related to it.
* @param other The observer cache.
* @param handler A [RelationHandler] that specifies how to remove related values from the observer cache.
*/
public suspend fun <R: Any> relatesTo(other: Cache<*, R>, handler: RelationHandler<Value, R>)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package dev.kord.cache.api.observables

import co.touchlab.stately.collections.ConcurrentMutableMap

/**
* An implementation of the [Cache] with [ConcurrentMutableMap].
* This implementation is thread-safe.
*
* @param relation The relation between this cache and other caches, used to remove related entries.
*/
public class ConcurrentCache<Key: Any, Value : Any>(
public val relation: Relation<Value>,
) : Cache<Key, Value> {

private val source: ConcurrentMutableMap<Key, Value> = ConcurrentMutableMap()

/**
* Gets the value associated with the given [key].
*
* @return The value associated with the given [key], or `null` if not found.
*/
override suspend fun get(key: Key): Value? {
return source[key]
}

/**
* Gets the first value that matches the [predicate] function.
*
* @return The first value that matches the [predicate] function, or `null` if not found.
*/
override suspend fun firstOrNull(predicate: (Value) -> Boolean): Value? {
return source.values.firstOrNull(predicate)
}

/**
* removes all values that match the [predicate] function.
*
* @param predicate The function used to determine which values to remove.
*/
override suspend fun removeAny(predicate: (Value) -> Boolean) {
source.asSequence()
.filter { (_, value) -> predicate(value) }
.forEach { (key, _) -> remove(key) }
}

override suspend fun filter(predicate: (Value) -> Boolean): Sequence<Value> =
source.asSequence()
.filter { (_, value) -> predicate(value) }
.map { it.value }


/**
* removes the value associated with the given [key].
*
* @return The value associated with the given [key], or `null` if not found.
*/
override suspend fun remove(key: Key) {
val value = source[key] ?: return
relation.remove(value)
source.remove(key)
}

override suspend fun set(key: Key, value: Value) {
source[key] = value
}


/**
* removes all entries from this cache.
*/
override suspend fun removeAll() {
val iterator = source.iterator()
while (iterator.hasNext()) {
val (_, value) = iterator.next()
relation.remove(value)
iterator.remove()
}
}


override suspend fun <R : Any> relatesTo(other: Cache<*, R>, handler: RelationHandler<Value, R>) {
relation.to(other, handler)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package dev.kord.cache.api.observables

/**
* A typealias for a function that determines the relationship between two entities of type `T` and `R`
* in a uni-directional link.
* The `value` parameter represents the entity of type `T` and the `friend` parameter represents the entity of type `R`.
* The function should return `true` if the two entities are related, or `false` otherwise.
*/
public typealias RelationHandler<T, R> = (value: T, friend: R) -> Boolean

/**
* A `Relation` is a uni-directional link between two entities of type `T` and `R`.
* A `Relation` is defined by a set of `RelationHandler`s which determine the relationship
* between two entities.
*
* @param T the type of the first entity in the relation.
*/
public interface Relation<T: Any> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this need to be a public interface now? it's no longer exposed by the other public interfaces so it could now just be an implementation detail

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be provided to customize the deletion process.
I've already added it to the implementation
What do you suggest we do with this one?


/**
* Removes the given [value] from all caches related to this relation.
*
* @param value the entity to remove from the relation.
*/
public suspend fun remove(value: T)


/**
* Associates an [Cache] of type `T` with this relation.
*
* @param cache the cache to associate with this relation.
* @param handler the `RelationHandler` that defines the relationship between entities of type `T` and `R`.
*/
public suspend fun <R: Any> to(cache: Cache<*, R>, handler: RelationHandler<T, R>)
}
2 changes: 1 addition & 1 deletion map/api/map.api
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public final class dev/kord/cache/map/MapLikeCollection$DefaultImpls {
public static fun contains (Ldev/kord/cache/map/MapLikeCollection;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class dev/kord/cache/map/MapLikeCollectionJvm {
public final class dev/kord/cache/map/MapLikeCollectionJvmx {
public static final fun weakHashMap (Ldev/kord/cache/map/MapLikeCollection$Companion;)Ldev/kord/cache/map/MapLikeCollection;
}

Expand Down