You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
2.3 KiB
JavaScript
93 lines
2.3 KiB
JavaScript
"use strict";
|
|
|
|
const util = require("util");
|
|
|
|
const errors = require("../errors");
|
|
const createWrapper = require("../util/function-wrapper");
|
|
const getValueType = require("../util/get-value-type");
|
|
|
|
let proto = {
|
|
_source: null,
|
|
set: null,
|
|
size: 0,
|
|
[Symbol.iterator]: createWrapper(Symbol.iterator),
|
|
[util.inspect.custom]: function () {
|
|
return this.valueOf();
|
|
},
|
|
clear: function () {
|
|
this._source.clear();
|
|
this.size = 0;
|
|
},
|
|
entries: createWrapper("entries"),
|
|
forEach: createWrapper("forEach"),
|
|
get: createWrapper("get"),
|
|
has: createWrapper("has"),
|
|
keys: createWrapper("keys"),
|
|
values: createWrapper("values"),
|
|
toString: createWrapper("toString"),
|
|
valueOf: createWrapper("valueOf"),
|
|
delete: function (key) {
|
|
let deleted = this._source.delete(key);
|
|
this.size = this._source.size;
|
|
|
|
if (deleted === false) {
|
|
throw new errors.ValidationError("Tried to delete non-existent key from guarded map", {
|
|
key: key,
|
|
nap: this._source
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
module.exports = function createGuardedMap(map, valueGuard, keyGuard, parent) {
|
|
function generateMapSignatureError() {
|
|
let wantedSignature = {
|
|
_guardedCollectionType: "map",
|
|
_keyType: keyGuard._rule,
|
|
_itemType: valueGuard._rule
|
|
};
|
|
|
|
return new errors.ValidationError(`Expected a Map or ${getValueType(wantedSignature)}, got ${getValueType(map)} instead`);
|
|
}
|
|
|
|
if (map._guardedCollectionType === "map") {
|
|
if (keyGuard === map._keyType && valueGuard === map._itemType) {
|
|
return map;
|
|
} else {
|
|
throw generateMapSignatureError();
|
|
}
|
|
} else if (map instanceof Map) {
|
|
function check(key, value) {
|
|
let keyGuardResult = keyGuard.call(parent, key);
|
|
let valueGuardResult = valueGuard.call(parent, value);
|
|
|
|
if (keyGuardResult === true && valueGuardResult === true) {
|
|
return true;
|
|
} else if (keyGuardResult !== true) {
|
|
throw keyGuardResult;
|
|
} else {
|
|
throw valueGuardResult;
|
|
}
|
|
}
|
|
|
|
for (let [key, value] of map.entries()) {
|
|
check(key, value);
|
|
}
|
|
|
|
return Object.assign(Object.create(proto), {
|
|
_source: map,
|
|
_guardedCollectionType: "map",
|
|
_itemType: valueGuard,
|
|
_keyType: keyGuard,
|
|
set: function (key, value) {
|
|
if (check(key, value) === true) {
|
|
this._source.set(key, value);
|
|
this.size = this._source.size;
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
throw generateMapSignatureError();
|
|
}
|
|
};
|