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

indigo.shared.QuickCache.scala Maven / Gradle / Ivy

The newest version!
package indigo.shared

/** QuickCache is a handy way to avoid expensive re-calculation of data. It is a side-effecting arrangement that Indigo
  * uses a lot internally, that can also be used by cautious game devs. Simple example:
  *
  * ```
  * given QuickCache[MyExpensiveObject] = QuickCache.empty
  *
  * QuickCache("key")(obj)
  * ```
  */
final class QuickCache[A](private val cache: scalajs.js.Dictionary[A]):

  def fetch(key: CacheKey): Option[A] =
    cache.get(key.toString)

  def add(key: CacheKey, value: => A): A = {
    val v = value
    cache.update(key.toString, v)
    v
  }

  def fetchOrAdd(key: CacheKey, disabled: Boolean, value: => A): A =
    if (disabled) value
    else
      try cache(key.toString)
      catch {
        case _: Throwable =>
          add(key, value)
      }

  def purgeAllNow(): Unit =
    cache.clear()

  def purgeAll(): QuickCache[A] = {
    cache.clear()
    this
  }

  def purge(key: CacheKey): QuickCache[A] = {
    cache.remove(key.toString)
    this
  }

  def keys: List[CacheKey] =
    cache.keys.map(CacheKey(_)).toList

  def all: List[(CacheKey, A)] =
    cache.toList.map(p => (CacheKey(p._1), p._2))

  def entryExistsFor(key: CacheKey): Boolean =
    cache.keys.exists(_ == key.toString)

  def unsafeFetch(key: CacheKey): A =
    cache(key.toString)

  def size: Int =
    cache.size

  def toMap[K](keyConvertor: CacheKey => K): Map[K, A] =
    cache.toMap.map { (pair: (String, A)) =>
      (keyConvertor(CacheKey(pair._1)), pair._2)
    }

object QuickCache:

  def apply[A](key: String)(value: => A)(implicit cache: QuickCache[A]): A =
    cache.fetchOrAdd(CacheKey(key), false, value)

  def apply[A](key: String, disabled: Boolean)(value: => A)(implicit cache: QuickCache[A]): A =
    cache.fetchOrAdd(CacheKey(key), disabled, value)

  def empty[A]: QuickCache[A] =
    new QuickCache[A](scalajs.js.Dictionary.empty[A])

opaque type CacheKey = String
object CacheKey:
  inline def apply(value: String): CacheKey = value

  extension (c: CacheKey) inline def toString: String = c

  given CanEqual[CacheKey, CacheKey] = CanEqual.derived

trait ToCacheKey[A]:
  def toKey(a: A): CacheKey

object ToCacheKey:
  def apply[A](f: A => CacheKey): ToCacheKey[A] =
    new ToCacheKey[A] {
      def toKey(a: A): CacheKey = f(a)
    }

  implicit val s: ToCacheKey[String] =
    ToCacheKey(str => CacheKey(str))

  implicit val i: ToCacheKey[Int] =
    ToCacheKey(p => CacheKey(p.toString))




© 2015 - 2024 Weber Informatics LLC | Privacy Policy