Created
December 20, 2021 13:56
-
-
Save julien-f/86de5dd69a240d803a6772f7f6180558 to your computer and use it in GitHub Desktop.
MultiKeyMap using serialization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const ensureArray = (value) => | |
Array.isArray(value) ? value : value === undefined ? [] : [value]; | |
exports.MultiKeyMap = class MultiKeyMap { | |
#data = new Map(); | |
#objects = new WeakMap(); | |
get size() { | |
return this.#data.size; | |
} | |
constructor(iterable) { | |
if (iterable !== undefined) { | |
for (const [key, value] of iterable) { | |
this.set(key, value); | |
} | |
} | |
} | |
clear() { | |
this.#data.clear(); | |
this.#objects.clear(); | |
} | |
delete(key) { | |
return this.#data.delete(this.#computeKey(key)); | |
} | |
get(key) { | |
return this.#data.get(this.#computeKey(key)); | |
} | |
has(key) { | |
return this.#data.has(this.#computeKey(key)); | |
} | |
set(key, value) { | |
this.#data.set(this.#computeKey(key), value); | |
} | |
#computeKey(parts) { | |
const key = []; | |
for (const part of ensureArray(parts)) { | |
const type = typeof part; | |
if (part == null) { | |
key.push(String(part)); | |
} else if (type === "object" || type === "function") { | |
const objects = this.#objects; | |
let id = objects.get(part); | |
if (id === undefined) { | |
id = Math.random().toString(36).slice(2); | |
this.#objects.set(part, id); | |
} | |
key.push("~ref~" + id); | |
} else if (type === "bigint") { | |
key.push(String(part) + "n"); | |
} else if (type === "symbol") { | |
throw new TypeError( | |
"Symbols as part of keys are not supported in this implementation" | |
); | |
} else { | |
key.push(JSON.stringify(part)); | |
} | |
} | |
return key.join(); | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const assert = require("assert").strict; | |
const { MultiKeyMap } = require("./MultiKeyMap.js"); | |
const map = new MultiKeyMap(); | |
const test = (key) => { | |
const value = {}; | |
const size = map.size; | |
map.set(key, value); | |
assert.equal(map.size, size + 1); | |
assert(map.has(key)); | |
assert.equal(map.get(key), value); | |
assert(map.delete(key)); | |
assert.equal(map.size, size); | |
assert(!map.has(key)); | |
assert.equal(map.get(key), undefined); | |
assert(!map.delete(key)); | |
}; | |
test([1, 2n, new Date(), /.*/, {}, Function.prototype]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment