status-react/src/status_im/utils/priority_map.cljs
yqrashawn 0a8993bbf1
refactor: reformat all clojure code with zprint (#14589)
Co-authored-by: refactor-only <auto@status.im>
2022-12-20 22:45:37 +08:00

258 lines
8.4 KiB
Clojure

(ns status-im.utils.priority-map
(:require [cljs.core :as core]
[cljs.reader :refer [register-tag-parser!]])
(:require-macros [cljs.core :as coreclj]))
;; from
;; https://github.com/tailrecursion/cljs-priority-map/blob/master/src/cljs/tailrecursion/priority_map.cljs
;; fixing `vals` and `keys` function
(deftype PersistentPriorityMap [priority->set-of-items item->priority meta keyfn ^:mutable __hash]
IPrintWithWriter
(-pr-writer [coll writer opts]
(let [pr-pair (fn [keyval]
(pr-sequential-writer writer #'cljs.core/pr-writer "" " " "" opts keyval))]
(pr-sequential-writer writer pr-pair "#status-im.utils.priority-map {" ", " "}" opts coll)))
IWithMeta
(-with-meta [_this meta]
(PersistentPriorityMap. priority->set-of-items item->priority meta keyfn __hash))
IMeta
(-meta [_this] meta)
ICollection
(-conj [this entry]
(if (vector? entry)
(-assoc this (-nth entry 0) (-nth entry 1))
(reduce -conj this entry)))
IEmptyableCollection
(-empty [_this]
#_{:clj-kondo/ignore [:unresolved-symbol]}
(with-meta
status-im.utils.priority-map.PersistentPriorityMap.EMPTY
meta))
IEquiv
(-equiv [_this other]
(-equiv item->priority other))
IHash
(-hash [this]
(coreclj/caching-hash this core/hash-unordered-coll __hash))
ISeqable
(-seq [_this]
(if keyfn
(seq (for [[_ item-set] priority->set-of-items
item item-set]
(MapEntry. item (item->priority item) nil)))
(seq (for [[priority item-set] priority->set-of-items
item item-set]
(MapEntry. item priority nil)))))
IReversible
(-rseq [_coll]
(if keyfn
(seq (for [[_ item-set] (rseq priority->set-of-items)
item item-set]
(MapEntry. item (item->priority item) nil)))
(seq (for [[priority item-set] (rseq priority->set-of-items)
item item-set]
(MapEntry. item priority nil)))))
ICounted
(-count [_this]
(count item->priority))
ILookup
(-lookup [_this item]
(get item->priority item))
(-lookup [_coll item not-found]
(get item->priority item not-found))
IStack
(-peek [_this]
(when-not (zero? (count item->priority))
(let [f (first priority->set-of-items)
item (first (val f))]
(if keyfn
[item (item->priority item)]
[item (key f)]))))
(-pop [_this]
(if (zero? (count item->priority))
(throw (js/Error. "Can't pop empty priority map"))
(let [f (first priority->set-of-items)
item-set (val f)
item (first item-set)
priority-key (key f)]
(if (= (count item-set) 1)
(PersistentPriorityMap.
(dissoc priority->set-of-items priority-key)
(dissoc item->priority item)
meta
keyfn
nil)
(PersistentPriorityMap.
(assoc priority->set-of-items priority-key (disj item-set item))
(dissoc item->priority item)
meta
keyfn
nil)))))
IAssociative
(-assoc [this item priority]
(if-let [current-priority (get item->priority item nil)]
(if (= current-priority priority)
this
(let [priority-key (keyfn priority)
current-priority-key (keyfn current-priority)
item-set (get priority->set-of-items current-priority-key)]
(if (= (count item-set) 1)
(PersistentPriorityMap.
(assoc (dissoc priority->set-of-items current-priority-key)
priority-key
(conj (get priority->set-of-items priority-key #{}) item))
(assoc item->priority item priority)
meta
keyfn
nil)
(PersistentPriorityMap.
(assoc priority->set-of-items
current-priority-key
(disj (get priority->set-of-items current-priority-key) item)
priority-key
(conj (get priority->set-of-items priority-key #{}) item))
(assoc item->priority item priority)
meta
keyfn
nil))))
(let [priority-key (keyfn priority)]
(PersistentPriorityMap.
(assoc priority->set-of-items
priority-key
(conj (get priority->set-of-items priority-key #{}) item))
(assoc item->priority item priority)
meta
keyfn
nil))))
(-contains-key? [_this item]
(contains? item->priority item))
IMap
(-dissoc [this item]
(let [priority (item->priority item ::not-found)]
(if (= priority ::not-found)
this
(let [priority-key (keyfn priority)
item-set (priority->set-of-items priority-key)]
(if (= (count item-set) 1)
(PersistentPriorityMap.
(dissoc priority->set-of-items priority-key)
(dissoc item->priority item)
meta
keyfn
nil)
(PersistentPriorityMap.
(assoc priority->set-of-items priority-key (disj item-set item))
(dissoc item->priority item)
meta
keyfn
nil))))))
ISorted
(-sorted-seq [this ascending?]
((if ascending? seq rseq) this))
(-sorted-seq-from [_this k ascending?]
(let [sets (if ascending?
(subseq priority->set-of-items >= k)
(rsubseq priority->set-of-items <= k))]
(if keyfn
(seq (for [[_ item-set] sets
item item-set]
[item (item->priority item)]))
(seq (for [[priority item-set] sets
item item-set]
[item priority])))))
(-entry-key [_this entry]
(keyfn (val entry)))
(-comparator [_this] compare)
IFn
(-invoke [this item]
(-lookup this item))
(-invoke [this item not-found]
(-lookup this item not-found)))
#_{:clj-kondo/ignore [:unresolved-symbol]}
(set! status-im.utils.priority-map.PersistentPriorityMap.EMPTY
(PersistentPriorityMap. (sorted-map) {} {} identity nil))
(defn- pm-empty-by
[comparator]
(PersistentPriorityMap. (sorted-map-by comparator) {} {} identity nil))
(defn- pm-empty-keyfn
([keyfn] (PersistentPriorityMap. (sorted-map) {} {} keyfn nil))
([keyfn comparator] (PersistentPriorityMap. (sorted-map-by comparator) {} {} keyfn nil)))
(defn- read-priority-map
[elems]
(if (map? elems)
(into PersistentPriorityMap.EMPTY elems)
(throw (js/Error "Priority map literal expects a map for its elements."))))
(register-tag-parser! "status-im.utils.priority-map" read-priority-map)
(defn priority-map
"keyval => key val
Returns a new priority map with supplied mappings."
([& keyvals]
#_{:clj-kondo/ignore [:unresolved-symbol]}
(loop [in (seq keyvals)
out status-im.utils.priority-map.PersistentPriorityMap.EMPTY]
(if in
(recur (nnext in) (assoc out (first in) (second in)))
out))))
(defn priority-map-by
"keyval => key val
Returns a new priority map with supplied
mappings, using the supplied comparator."
([comparator & keyvals]
(loop [in (seq keyvals)
out (pm-empty-by comparator)]
(if in
(recur (nnext in) (assoc out (first in) (second in)))
out))))
(defn priority-map-keyfn
"keyval => key val
Returns a new priority map with supplied
mappings, using the supplied keyfn."
([keyfn & keyvals]
(loop [in (seq keyvals)
out (pm-empty-keyfn keyfn)]
(if in
(recur (nnext in) (assoc out (first in) (second in)))
out))))
(defn priority-map-keyfn-by
"keyval => key val
Returns a new priority map with supplied
mappings, using the supplied keyfn and comparator."
([keyfn comparator & keyvals]
(loop [in (seq keyvals)
out (pm-empty-keyfn keyfn comparator)]
(if in
(recur (nnext in) (assoc out (first in) (second in)))
out))))
(def empty-message-map
(priority-map-keyfn-by :clock-value >))
(def empty-transaction-map
(priority-map-keyfn-by :block #(< (int %1) (int %2))))