@itwin/core-bentley
Version:
Bentley JavaScript core components
103 lines • 3.53 kB
JavaScript
;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Collections
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.TupleKeyedMap = void 0;
/** A map similar to the standard JavaScript Map collection except that the keys must be a tuple
* (javascript array), and two keys are considered equal if their elements in order are strict-equal,
* and the tuples have the same amount of elements
*
* This means you can use array literals to key data in Maps that would otherwise be reference-compared
* if using JavaScript's built in Map
*
* Note that JavaScript's Map type, unlike this one that uses strict equality, uses instead
* SameValueZero equality comparison
* @see https://262.ecma-international.org/6.0/#sec-samevaluezero
*
* ```js
* const map = new TupleKeyedMap([[1,"y"], "value"]);
* const value = map.get([1, "y"]); // a normal map would identify these keys as different because they are independent objects
* ```
*
* It is implemented by each index of the tuple key being used as a singular key into a submap
* @note this only implements a subset of the Map interface
* @public
*/
class TupleKeyedMap {
_map = new Map();
// argument types match those of Map
constructor(entries) {
if (entries)
for (const [k, v] of entries) {
this.set(k, v);
}
}
clear() {
return this._map.clear();
}
makeKeyError() {
return Error("A Bad key was used, it didn't match the key type of the the map.");
}
get(key) {
let cursor = this._map;
for (const subkey of key) {
if (!(cursor instanceof Map))
throw this.makeKeyError();
cursor = cursor.get(subkey);
if (cursor === undefined)
return undefined;
}
if (cursor instanceof Map)
throw this.makeKeyError();
return cursor;
}
has(key) {
return this.get(key) !== undefined;
}
set(key, value) {
let cursor = this._map;
for (let i = 0; i < key.length - 1; ++i) {
const subkey = key[i];
let next = cursor.get(subkey);
if (next === undefined) {
next = new Map();
cursor.set(subkey, next);
}
cursor = next;
}
const finalSubkey = key[key.length - 1];
if (!(cursor instanceof Map))
throw this.makeKeyError();
cursor.set(finalSubkey, value);
this._size++;
return this;
}
*[Symbol.iterator]() {
function* impl(map, keyPrefix) {
for (const [k, v] of map) {
const nextKey = [...keyPrefix, k];
if (v instanceof Map) {
yield* impl(v, nextKey);
}
else {
yield [nextKey, v];
}
}
}
yield* impl(this._map, []);
}
_size = 0;
get size() {
return this._size;
}
get [Symbol.toStringTag]() {
return this.constructor.name;
}
}
exports.TupleKeyedMap = TupleKeyedMap;
//# sourceMappingURL=TupleKeyedMap.js.map