@thi.ng/associative
Version:
ES Map/Set-compatible implementations with customizable equality semantics & supporting operations
155 lines (154 loc) • 3.95 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
for (var i = decorators.length - 1, decorator; i >= 0; i--)
if (decorator = decorators[i])
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
if (kind && result) __defProp(target, key, result);
return result;
};
import { SEMAPHORE } from "@thi.ng/api/api";
import { isPlainObject } from "@thi.ng/checks/is-plain-object";
import { equiv } from "@thi.ng/equiv";
import { pairs } from "@thi.ng/transducers/pairs";
import { ArraySet } from "./array-set.js";
import { dissoc } from "./dissoc.js";
import { __equivMap } from "./internal/equiv.js";
import { __inspectable } from "./internal/inspect.js";
import { into } from "./into.js";
const __private = /* @__PURE__ */ new WeakMap();
const __map = (map) => __private.get(map).map;
let EquivMap = class extends Map {
/**
* Creates a new instance with optional initial key-value pairs and provided
* options. If no `opts` are given, uses `ArraySet` for storing canonical
* keys and
* [`equiv`](https://docs.thi.ng/umbrella/equiv/functions/equiv.html) for
* checking key equivalence.
*
* @param pairs - key-value pairs
* @param opts - config options
*/
constructor(pairs2, opts) {
super();
const _opts = { equiv, keys: ArraySet, ...opts };
__private.set(this, {
keys: new _opts.keys(null, { equiv: _opts.equiv }),
map: /* @__PURE__ */ new Map(),
opts: _opts
});
if (pairs2) {
this.into(pairs2);
}
}
[Symbol.iterator]() {
return this.entries();
}
get [Symbol.species]() {
return EquivMap;
}
get [Symbol.toStringTag]() {
return "EquivMap";
}
get size() {
return __private.get(this).keys.size;
}
clear() {
const { keys, map } = __private.get(this);
keys.clear();
map.clear();
}
empty() {
return new EquivMap(null, __private.get(this).opts);
}
copy() {
const { keys, map, opts } = __private.get(this);
const m = new EquivMap();
__private.set(m, {
keys: keys.copy(),
map: new Map(map),
opts
});
return m;
}
equiv(o) {
return __equivMap(this, o);
}
delete(key) {
const { keys, map } = __private.get(this);
key = keys.get(key, SEMAPHORE);
if (key !== SEMAPHORE) {
map.delete(key);
keys.delete(key);
return true;
}
return false;
}
dissoc(keys) {
return dissoc(this, keys);
}
/**
* The key & value args given the callback `fn` MUST be treated as
* readonly/immutable. This could be enforced via TS, but would
* break ES6 Map interface contract.
*
* @param fn -
* @param thisArg -
*/
forEach(fn, thisArg) {
for (let pair of __map(this)) {
fn.call(thisArg, pair[1], pair[0], this);
}
}
get(key, notFound) {
const { keys, map } = __private.get(this);
key = keys.get(key, SEMAPHORE);
if (key !== SEMAPHORE) {
return map.get(key);
}
return notFound;
}
has(key) {
return __private.get(this).keys.has(key);
}
set(key, value) {
const { keys, map } = __private.get(this);
const k = keys.get(key, SEMAPHORE);
if (k !== SEMAPHORE) {
map.set(k, value);
} else {
keys.add(key);
map.set(key, value);
}
return this;
}
into(pairs2) {
return into(this, pairs2);
}
entries() {
return __map(this).entries();
}
keys() {
return __map(this).keys();
}
values() {
return __map(this).values();
}
opts() {
return __private.get(this).opts;
}
};
EquivMap = __decorateClass([
__inspectable
], EquivMap);
function defEquivMap(src, opts) {
return new EquivMap(
isPlainObject(src) ? pairs(src) : src,
opts
);
}
export {
EquivMap,
defEquivMap
};