UNPKG

@rimbu/multimap

Version:

An immutable Map where each key can have multiple values

553 lines 21.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MultiMapContext = exports.MultiMapBuilder = exports.MultiMapNonEmpty = exports.MultiMapEmpty = void 0; var tslib_1 = require("tslib"); var base_1 = require("@rimbu/base"); var map_custom_1 = require("@rimbu/collection-types/map-custom"); var common_1 = require("@rimbu/common"); var stream_1 = require("@rimbu/stream"); var custom_1 = require("@rimbu/stream/custom"); var MultiMapEmpty = /** @class */ (function (_super) { tslib_1.__extends(MultiMapEmpty, _super); function MultiMapEmpty(context) { var _this = _super.call(this) || this; _this.context = context; return _this; } Object.defineProperty(MultiMapEmpty.prototype, "keyMap", { get: function () { return this.context.keyMapContext.empty(); }, enumerable: false, configurable: true }); Object.defineProperty(MultiMapEmpty.prototype, "keySize", { get: function () { return 0; }, enumerable: false, configurable: true }); MultiMapEmpty.prototype.streamKeys = function () { return stream_1.Stream.empty(); }; MultiMapEmpty.prototype.streamValues = function () { return stream_1.Stream.empty(); }; MultiMapEmpty.prototype.hasKey = function () { return false; }; MultiMapEmpty.prototype.hasEntry = function () { return false; }; MultiMapEmpty.prototype.add = function (key, value) { var values = this.context.keyMapValuesContext.of(value); var keyMap = this.context.keyMapContext.of([ key, values, ]); return this.context.createNonEmpty(keyMap, 1); }; MultiMapEmpty.prototype.addEntries = function (entries) { return this.context.from(entries); }; MultiMapEmpty.prototype.getValues = function () { return this.context.keyMapValuesContext.empty(); }; MultiMapEmpty.prototype.setValues = function (key, values) { var valueSet = this.context.keyMapValuesContext.from(values); if (!valueSet.nonEmpty()) return this; var keyMap = this.context.keyMapContext.of([ key, valueSet, ]); return this.context.createNonEmpty(keyMap, valueSet.size); }; MultiMapEmpty.prototype.modifyAt = function (atKey, options) { if (undefined === options.ifNew) return this; return this.setValues(atKey, (0, common_1.OptLazy)(options.ifNew)); }; MultiMapEmpty.prototype.removeKey = function () { return this; }; MultiMapEmpty.prototype.removeKeys = function () { return this; }; MultiMapEmpty.prototype.removeKeyAndGet = function () { return undefined; }; MultiMapEmpty.prototype.removeEntry = function () { return this; }; MultiMapEmpty.prototype.removeEntries = function () { return this; }; MultiMapEmpty.prototype.toBuilder = function () { return this.context.builder(); }; MultiMapEmpty.prototype.toString = function () { return "".concat(this.context.typeTag, "()"); }; MultiMapEmpty.prototype.toJSON = function () { return { dataType: this.context.typeTag, value: [], }; }; return MultiMapEmpty; }(map_custom_1.EmptyBase)); exports.MultiMapEmpty = MultiMapEmpty; var MultiMapNonEmpty = /** @class */ (function (_super) { tslib_1.__extends(MultiMapNonEmpty, _super); function MultiMapNonEmpty(context, keyMap, size) { var _this = _super.call(this) || this; _this.context = context; _this.keyMap = keyMap; _this.size = size; return _this; } MultiMapNonEmpty.prototype.assumeNonEmpty = function () { return this; }; MultiMapNonEmpty.prototype.asNormal = function () { return this; }; MultiMapNonEmpty.prototype.copy = function (keyMap, size) { if (keyMap === this.keyMap) return this; return this.context.createNonEmpty(keyMap, size); }; MultiMapNonEmpty.prototype.copyE = function (keyMap, size) { if (keyMap.nonEmpty()) { return this.copy(keyMap.assumeNonEmpty(), size); } return this.context.empty(); }; MultiMapNonEmpty.prototype.stream = function () { return this.keyMap .stream() .flatMap(function (_a) { var _b = tslib_1.__read(_a, 2), key = _b[0], values = _b[1]; return values.stream().map(function (v) { return [key, v]; }); }); }; MultiMapNonEmpty.prototype.streamKeys = function () { return this.keyMap.streamKeys(); }; MultiMapNonEmpty.prototype.streamValues = function () { return this.keyMap .streamValues() .flatMap(function (values) { return values.stream(); }); }; Object.defineProperty(MultiMapNonEmpty.prototype, "keySize", { get: function () { return this.keyMap.size; }, enumerable: false, configurable: true }); MultiMapNonEmpty.prototype.hasKey = function (key) { return this.keyMap.hasKey(key); }; MultiMapNonEmpty.prototype.hasEntry = function (key, value) { var _a; var values = this.keyMap.get(key); return (_a = values === null || values === void 0 ? void 0 : values.has(value)) !== null && _a !== void 0 ? _a : false; }; MultiMapNonEmpty.prototype.getValues = function (key) { return this.keyMap.get(key, this.context.keyMapValuesContext.empty()); }; MultiMapNonEmpty.prototype.add = function (key, value) { var _this = this; var newSize = this.size; var newKeyMap = this.keyMap .modifyAt(key, { ifNew: function () { newSize++; return _this.context.keyMapValuesContext.of(value); }, ifExists: function (values) { var newValues = values.add(value); if (newValues === values) return values; newSize -= values.size; newSize += newValues.size; return newValues; }, }) .assumeNonEmpty(); return this.copy(newKeyMap, newSize); }; MultiMapNonEmpty.prototype.addEntries = function (entries) { if ((0, custom_1.isEmptyStreamSourceInstance)(entries)) return this; var builder = this.toBuilder(); builder.addEntries(entries); return builder.build().assumeNonEmpty(); }; MultiMapNonEmpty.prototype.setValues = function (key, values) { return this.modifyAt(key, { ifNew: values, ifExists: function () { return values; } }); }; MultiMapNonEmpty.prototype.removeKey = function (key) { if (!this.context.keyMapContext.isValidKey(key)) return this; return this.modifyAt(key, { ifExists: function () { return []; } }); }; MultiMapNonEmpty.prototype.removeKeys = function (keys) { if ((0, custom_1.isEmptyStreamSourceInstance)(keys)) return this; var builder = this.toBuilder(); builder.removeKeys(keys); return builder.build(); }; MultiMapNonEmpty.prototype.removeKeyAndGet = function (key) { if (!this.context.keyMapContext.isValidKey(key)) return undefined; var removed = undefined; var result = this.modifyAt(key, { ifExists: function (values) { removed = values; return []; }, }); if (undefined === removed) return undefined; return [result, removed]; }; MultiMapNonEmpty.prototype.removeEntry = function (key, value) { if (!this.context.keyMapContext.isValidKey(key)) return this; return this.modifyAt(key, { ifExists: function (values) { return values.remove(value); }, }); }; MultiMapNonEmpty.prototype.removeEntries = function (entries) { if ((0, custom_1.isEmptyStreamSourceInstance)(entries)) return this; var builder = this.toBuilder(); builder.removeEntries(entries); return builder.build(); }; MultiMapNonEmpty.prototype.filter = function (pred, options) { if (options === void 0) { options = {}; } var builder = this.context.builder(); builder.addEntries(this.stream().filter(pred, options)); if (builder.size === this.size) return this; return builder.build(); }; MultiMapNonEmpty.prototype.forEach = function (f, options) { if (options === void 0) { options = {}; } var _a = options.state, state = _a === void 0 ? (0, common_1.TraverseState)() : _a; if (state.halted) return; this.stream().forEach(f, { state: state }); }; MultiMapNonEmpty.prototype.modifyAt = function (atKey, options) { var _this = this; var newSize = this.size; var ifNew = options.ifNew, ifExists = options.ifExists; var newKeyMap = this.keyMap.modifyAt(atKey, { ifNew: function (none) { if (undefined === ifNew) return none; var newValueStream = (0, common_1.OptLazy)(ifNew); var newValues = _this.context.keyMapValuesContext.from(newValueStream); if (!newValues.nonEmpty()) return none; newSize += newValues.size; return newValues; }, ifExists: function (currentValues, remove) { if (undefined === ifExists) return currentValues; var newValueStream = ifExists instanceof Function ? ifExists(currentValues) : ifExists; var newValues = _this.context.keyMapValuesContext.from(newValueStream); if (!newValues.nonEmpty()) { newSize -= currentValues.size; return remove; } newSize -= currentValues.size; newSize += newValues.size; return newValues; }, }); return this.copyE(newKeyMap, newSize); }; MultiMapNonEmpty.prototype.toArray = function () { return this.stream().toArray(); }; MultiMapNonEmpty.prototype.toString = function () { return this.keyMap.stream().join({ start: "".concat(this.context.typeTag, "("), sep: ', ', end: ')', valueToString: function (_a) { var _b = tslib_1.__read(_a, 2), key = _b[0], values = _b[1]; return "".concat(key, " -> ").concat(values.stream().join({ start: '[', sep: ', ', end: ']' })); }, }); }; MultiMapNonEmpty.prototype.toJSON = function () { return { dataType: this.context.typeTag, value: this.keyMap .stream() .map(function (entry) { return [entry[0], entry[1].toArray()]; }) .toArray(), }; }; MultiMapNonEmpty.prototype.toBuilder = function () { return this.context.createBuilder(this); }; return MultiMapNonEmpty; }(map_custom_1.NonEmptyBase)); exports.MultiMapNonEmpty = MultiMapNonEmpty; var MultiMapBuilder = /** @class */ (function () { function MultiMapBuilder(context, source) { var _this = this; this.context = context; this.source = source; this._lock = 0; this._size = 0; // prettier-ignore this.getValues = function (key) { var _a, _b, _c, _d; return ((_d = (_b = (_a = _this.source) === null || _a === void 0 ? void 0 : _a.getValues(key)) !== null && _b !== void 0 ? _b : (_c = _this.keyMap.get(key)) === null || _c === void 0 ? void 0 : _c.build()) !== null && _d !== void 0 ? _d : _this.context.keyMapValuesContext.empty()); }; // prettier-ignore this.hasKey = function (key) { var _a, _b; return (_b = (_a = _this.source) === null || _a === void 0 ? void 0 : _a.hasKey(key)) !== null && _b !== void 0 ? _b : _this.keyMap.hasKey(key); }; // prettier-ignore this.hasEntry = function (key, value) { var _a, _b, _c, _d; return ((_d = (_b = (_a = _this.source) === null || _a === void 0 ? void 0 : _a.hasEntry(key, value)) !== null && _b !== void 0 ? _b : (_c = _this.keyMap.get(key)) === null || _c === void 0 ? void 0 : _c.has(value)) !== null && _d !== void 0 ? _d : false); }; this.add = function (key, value) { _this.checkLock(); var changed = true; _this.keyMap.modifyAt(key, { ifNew: function () { _this._size++; var valueBuilder = _this.context.keyMapValuesContext.builder(); valueBuilder.add(value); return valueBuilder; }, ifExists: function (valueBuilder) { _this._size -= valueBuilder.size; changed = valueBuilder.add(value); _this._size += valueBuilder.size; return valueBuilder; }, }); if (changed) _this.source = undefined; return changed; }; this.addEntries = function (source) { _this.checkLock(); return stream_1.Stream.applyFilter(source, { pred: _this.add }).count() > 0; }; this.setValues = function (key, source) { _this.checkLock(); var values = _this.context.keyMapValuesContext.from(source).toBuilder(); var size = values.size; if (size <= 0) return _this.removeKey(key); return _this.keyMap.modifyAt(key, { ifNew: function () { _this._size += size; _this.source = undefined; return values; }, ifExists: function (oldValues) { _this._size -= oldValues.size; _this._size += size; _this.source = undefined; return values; }, }); }; this.removeEntry = function (key, value) { _this.checkLock(); if (!_this.context.keyMapContext.isValidKey(key)) return false; var changed = false; _this.keyMap.modifyAt(key, { ifExists: function (valueBuilder, remove) { if (valueBuilder.remove(value)) { _this._size--; changed = true; } if (valueBuilder.size <= 0) return remove; return valueBuilder; }, }); if (changed) _this.source = undefined; return changed; }; this.removeEntries = function (entries) { _this.checkLock(); return stream_1.Stream.applyFilter(entries, { pred: _this.removeEntry }).count() > 0; }; // prettier-ignore this.removeKey = function (key) { _this.checkLock(); if (!_this.context.keyMapContext.isValidKey(key)) return false; var changed = _this.keyMap.modifyAt(key, { ifExists: function (valueBuilder, remove) { _this._size -= valueBuilder.size; return remove; }, }); if (changed) _this.source = undefined; return changed; }; // prettier-ignore this.removeKeys = function (keys) { _this.checkLock(); return stream_1.Stream.from(keys).filterPure({ pred: _this.removeKey }).count() > 0; }; this.forEach = function (f, options) { if (options === void 0) { options = {}; } var _a = options.reversed, reversed = _a === void 0 ? false : _a, _b = options.state, state = _b === void 0 ? (0, common_1.TraverseState)() : _b; if (state.halted) return; _this._lock++; _this.keyMap.forEach(function (_a, _, outerHalt) { var _b = tslib_1.__read(_a, 2), key = _b[0], values = _b[1]; values.forEach(function (value, index, halt) { return f([key, value], index, halt); }, { reversed: reversed, state: state, }); if (state.halted) outerHalt(); }, { reversed: reversed }); _this._lock--; }; this.build = function () { if (undefined !== _this.source) return _this.source; if (_this.isEmpty) return _this.context.empty(); return _this.context.createNonEmpty(_this.keyMap .buildMapValues(function (values) { return values.build().assumeNonEmpty(); }) .assumeNonEmpty(), _this.size); }; if (undefined !== source) this._size = source.size; } Object.defineProperty(MultiMapBuilder.prototype, "keyMap", { get: function () { if (undefined === this._keyMap) { if (undefined === this.source) { this._keyMap = this.context.keyMapContext.builder(); } else { this._keyMap = this.source.keyMap .mapValues(function (v) { return v.toBuilder(); }) .toBuilder(); } } return this._keyMap; }, enumerable: false, configurable: true }); MultiMapBuilder.prototype.checkLock = function () { if (this._lock) base_1.RimbuError.throwModifiedBuilderWhileLoopingOverItError(); }; Object.defineProperty(MultiMapBuilder.prototype, "size", { get: function () { return this._size; }, enumerable: false, configurable: true }); Object.defineProperty(MultiMapBuilder.prototype, "isEmpty", { get: function () { return this.size === 0; }, enumerable: false, configurable: true }); return MultiMapBuilder; }()); exports.MultiMapBuilder = MultiMapBuilder; var MultiMapContext = /** @class */ (function () { function MultiMapContext(typeTag, keyMapContext, keyMapValuesContext) { var _this = this; this.typeTag = typeTag; this.keyMapContext = keyMapContext; this.keyMapValuesContext = keyMapValuesContext; this._empty = Object.freeze(new MultiMapEmpty(this)); this.empty = function () { return _this._empty; }; this.from = function () { var sources = []; for (var _i = 0; _i < arguments.length; _i++) { sources[_i] = arguments[_i]; } var builder = _this.builder(); var i = -1; var length = sources.length; while (++i < length) { var source = sources[i]; if ((0, custom_1.isEmptyStreamSourceInstance)(source)) continue; if (builder.isEmpty && _this.isNonEmptyInstance(source) && source.context === _this) { if (i === length - 1) return source; builder = source.toBuilder(); continue; } builder.addEntries(source); } return builder.build(); }; this.of = function () { var entries = []; for (var _i = 0; _i < arguments.length; _i++) { entries[_i] = arguments[_i]; } return _this.from(entries); }; this.builder = function () { return new MultiMapBuilder(_this); }; this.reducer = function (source) { return stream_1.Reducer.create(function () { return undefined === source ? _this.builder() : _this.from(source).toBuilder(); }, function (builder, entry) { builder.add(entry[0], entry[1]); return builder; }, function (builder) { return builder.build(); }); }; } MultiMapContext.prototype.isNonEmptyInstance = function (source) { return source instanceof MultiMapNonEmpty; }; MultiMapContext.prototype.createNonEmpty = function (keyMap, size) { return new MultiMapNonEmpty(this, keyMap, size); }; MultiMapContext.prototype.createBuilder = function (source) { return new MultiMapBuilder(this, source); }; return MultiMapContext; }()); exports.MultiMapContext = MultiMapContext; //# sourceMappingURL=base.cjs.map