TransientArrayMap
(TransientArrayMap. editable? len arr)
(deftype TransientArrayMap [^:mutable ^boolean editable?
^:mutable len
arr]
ICounted
(-count [tcoll]
(if editable?
(quot len 2)
(throw (js/Error. "count after persistent!"))))
ILookup
(-lookup [tcoll k]
(-lookup tcoll k nil))
(-lookup [tcoll k not-found]
(if editable?
(let [idx (array-map-index-of tcoll k)]
(if (== idx -1)
not-found
(aget arr (inc idx))))
(throw (js/Error. "lookup after persistent!"))))
ITransientCollection
(-conj! [tcoll o]
(if editable?
(cond
(map-entry? o)
(-assoc! tcoll (key o) (val o))
(vector? o)
(-assoc! tcoll (o 0) (o 1))
:else
(loop [es (seq o) tcoll tcoll]
(if-let [e (first es)]
(recur (next es)
(-assoc! tcoll (key e) (val e)))
tcoll)))
(throw (js/Error. "conj! after persistent!"))))
(-persistent! [tcoll]
(if editable?
(do (set! editable? false)
(PersistentArrayMap. nil (quot len 2) arr nil))
(throw (js/Error. "persistent! called twice"))))
ITransientAssociative
(-assoc! [tcoll key val]
(if editable?
(let [idx (array-map-index-of tcoll key)]
(if (== idx -1)
(if (<= (+ len 2) (* 2 (.-HASHMAP-THRESHOLD PersistentArrayMap)))
(do (set! len (+ len 2))
(.push arr key)
(.push arr val)
tcoll)
(assoc! (array->transient-hash-map len arr) key val))
(if (identical? val (aget arr (inc idx)))
tcoll
(do (aset arr (inc idx) val)
tcoll))))
(throw (js/Error. "assoc! after persistent!"))))
ITransientMap
(-dissoc! [tcoll key]
(if editable?
(let [idx (array-map-index-of tcoll key)]
(when (>= idx 0)
(aset arr idx (aget arr (- len 2)))
(aset arr (inc idx) (aget arr (dec len)))
(doto arr .pop .pop)
(set! len (- len 2)))
tcoll)
(throw (js/Error. "dissoc! after persistent!"))))
IFn
(-invoke [tcoll key]
(-lookup tcoll key nil))
(-invoke [tcoll key not-found]
(-lookup tcoll key not-found)))