@rimbu/table
Version:
Immutable spreadsheet-like data structures containing row keys, column keys, and cell values
734 lines • 27.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TableContext = exports.TableBuilder = exports.TableNonEmpty = exports.TableEmpty = 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 TableEmpty = /** @class */ (function (_super) {
tslib_1.__extends(TableEmpty, _super);
function TableEmpty(context) {
var _this = _super.call(this) || this;
_this.context = context;
return _this;
}
TableEmpty.prototype.set = function (row, column, value) {
var columnMap = this.context.columnContext.of([column, value]);
var rowMap = this.context.rowContext.of([row, columnMap]);
return this.context.createNonEmpty(rowMap, 1);
};
Object.defineProperty(TableEmpty.prototype, "rowMap", {
get: function () {
return this.context.rowContext.empty();
},
enumerable: false,
configurable: true
});
Object.defineProperty(TableEmpty.prototype, "amountRows", {
get: function () {
return 0;
},
enumerable: false,
configurable: true
});
TableEmpty.prototype.streamRows = function () {
return stream_1.Stream.empty();
};
TableEmpty.prototype.streamValues = function () {
return stream_1.Stream.empty();
};
TableEmpty.prototype.addEntry = function (entry) {
return this.set(entry[0], entry[1], entry[2]);
};
TableEmpty.prototype.addEntries = function (entries) {
return this.context.from(entries);
};
TableEmpty.prototype.remove = function () {
return this;
};
TableEmpty.prototype.removeRow = function () {
return this;
};
TableEmpty.prototype.removeRows = function () {
return this;
};
TableEmpty.prototype.removeAndGet = function () {
return undefined;
};
TableEmpty.prototype.removeRowAndGet = function () {
return undefined;
};
TableEmpty.prototype.removeEntries = function () {
return this;
};
TableEmpty.prototype.hasRowKey = function () {
return false;
};
TableEmpty.prototype.hasValueAt = function () {
return false;
};
TableEmpty.prototype.get = function (row, column, otherwise) {
return (0, common_1.OptLazy)(otherwise);
};
TableEmpty.prototype.getRow = function () {
return this.context.columnContext.empty();
};
TableEmpty.prototype.modifyAt = function (row, column, options) {
if (undefined !== options.ifNew) {
var value = (0, common_1.OptLazyOr)(options.ifNew, base_1.Token);
if (base_1.Token === value)
return this;
return this.set(row, column, value);
}
return this;
};
TableEmpty.prototype.updateAt = function () {
return this;
};
TableEmpty.prototype.filterRows = function () {
return this;
};
TableEmpty.prototype.mapValues = function () {
return this;
};
TableEmpty.prototype.toBuilder = function () {
return this.context.builder();
};
TableEmpty.prototype.toString = function () {
return "".concat(this.context.typeTag, "()");
};
TableEmpty.prototype.toJSON = function () {
return {
dataType: this.context.typeTag,
value: [],
};
};
return TableEmpty;
}(map_custom_1.EmptyBase));
exports.TableEmpty = TableEmpty;
var TableNonEmpty = /** @class */ (function (_super) {
tslib_1.__extends(TableNonEmpty, _super);
function TableNonEmpty(context, rowMap, size) {
var _this = _super.call(this) || this;
_this.context = context;
_this.rowMap = rowMap;
_this.size = size;
return _this;
}
TableNonEmpty.prototype.assumeNonEmpty = function () {
return this;
};
TableNonEmpty.prototype.asNormal = function () {
return this;
};
TableNonEmpty.prototype.copy = function (rowMap, size) {
if (rowMap === this.rowMap)
return this;
return this.context.createNonEmpty(rowMap, size);
};
TableNonEmpty.prototype.copyE = function (rowMap, size) {
if (rowMap.nonEmpty()) {
return this.copy(rowMap.assumeNonEmpty(), size);
}
return this.context.empty();
};
TableNonEmpty.prototype.stream = function () {
return this.rowMap
.stream()
.flatMap(function (_a) {
var _b = tslib_1.__read(_a, 2), row = _b[0], columns = _b[1];
return columns
.stream()
.map(function (_a) {
var _b = tslib_1.__read(_a, 2), column = _b[0], value = _b[1];
return [row, column, value];
});
});
};
TableNonEmpty.prototype.streamRows = function () {
return this.rowMap.streamKeys();
};
TableNonEmpty.prototype.streamValues = function () {
return this.rowMap
.streamValues()
.flatMap(function (columns) { return columns.streamValues(); });
};
Object.defineProperty(TableNonEmpty.prototype, "amountRows", {
get: function () {
return this.rowMap.size;
},
enumerable: false,
configurable: true
});
TableNonEmpty.prototype.hasRowKey = function (row) {
return this.rowMap.hasKey(row);
};
TableNonEmpty.prototype.hasValueAt = function (row, column) {
var token = Symbol();
return token !== this.get(row, column, token);
};
TableNonEmpty.prototype.get = function (row, column, otherwise) {
var token = Symbol();
var result = this.rowMap.get(row, token);
if (token === result)
return (0, common_1.OptLazy)(otherwise);
return result.get(column, otherwise);
};
TableNonEmpty.prototype.getRow = function (row) {
return this.rowMap.get(row, this.context.columnContext.empty());
};
TableNonEmpty.prototype.set = function (row, column, value) {
return this.modifyAt(row, column, {
ifNew: value,
ifExists: function () { return value; },
}).assumeNonEmpty();
};
TableNonEmpty.prototype.addEntry = function (entry) {
return this.set(entry[0], entry[1], entry[2]);
};
TableNonEmpty.prototype.addEntries = function (entries) {
if ((0, custom_1.isEmptyStreamSourceInstance)(entries))
return this;
var builder = this.toBuilder();
builder.addEntries(entries);
return builder.build().assumeNonEmpty();
};
TableNonEmpty.prototype.modifyAt = function (row, column, options) {
var _this = this;
var newSize = this.size;
var newRowMap = this.rowMap.modifyAt(row, {
ifNew: function (none) {
var ifNew = options.ifNew;
if (undefined === ifNew) {
return none;
}
var value = (0, common_1.OptLazyOr)(ifNew, none);
if (none === value) {
return none;
}
newSize++;
return _this.context.columnContext.of([column, value]);
},
ifExists: function (row, remove) {
var newRow = row.modifyAt(column, options);
if (newRow === row) {
return row;
}
if (!newRow.nonEmpty()) {
return remove;
}
newSize += newRow.size - row.size;
return newRow;
},
});
return this.copyE(newRowMap, newSize);
};
TableNonEmpty.prototype.updateAt = function (row, column, update) {
if (!this.context.rowContext.isValidKey(row))
return this;
if (!this.context.columnContext.isValidKey(column))
return this;
return this.modifyAt(row, column, {
ifExists: function (value) { return (0, common_1.Update)(value, update); },
}).assumeNonEmpty();
};
TableNonEmpty.prototype.remove = function (row, column) {
var _a;
var resultOpt = this.removeAndGet(row, column);
return (_a = resultOpt === null || resultOpt === void 0 ? void 0 : resultOpt[0]) !== null && _a !== void 0 ? _a : this;
};
TableNonEmpty.prototype.removeRow = function (row) {
var _a;
var resultOpt = this.removeRowAndGet(row);
return (_a = resultOpt === null || resultOpt === void 0 ? void 0 : resultOpt[0]) !== null && _a !== void 0 ? _a : this;
};
TableNonEmpty.prototype.removeRows = function (rows) {
if ((0, custom_1.isEmptyStreamSourceInstance)(rows))
return this;
var builder = this.toBuilder();
builder.removeRows(rows);
return builder.build();
};
TableNonEmpty.prototype.removeAndGet = function (row, column) {
if (!this.context.rowContext.isValidKey(row))
return undefined;
if (!this.context.columnContext.isValidKey(column))
return undefined;
var newSize = this.size;
var token = Symbol();
var removedValue = token;
var newRows = this.rowMap.modifyAt(row, {
ifExists: function (columns, remove) {
var newColumns = columns.modifyAt(column, {
ifExists: function (currentValue, remove) {
removedValue = currentValue;
newSize--;
return remove;
},
});
if (newColumns.nonEmpty())
return newColumns;
return remove;
},
});
if (token === removedValue)
return undefined;
var newSelf = this.copyE(newRows, newSize);
return [newSelf, removedValue];
};
TableNonEmpty.prototype.removeRowAndGet = function (row) {
if (!this.context.rowContext.isValidKey(row))
return undefined;
var newSize = this.size;
var removedRow;
var newRows = this.rowMap.modifyAt(row, {
ifExists: function (columns, remove) {
removedRow = columns;
newSize -= columns.size;
return remove;
},
});
if (undefined === removedRow)
return undefined;
var newSelf = this.copyE(newRows, newSize);
return [newSelf, removedRow];
};
TableNonEmpty.prototype.removeEntries = function (entries) {
if ((0, custom_1.isEmptyStreamSourceInstance)(entries))
return this;
var builder = this.toBuilder();
builder.removeEntries(entries);
return builder.build();
};
TableNonEmpty.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;
var rowIt = this.rowMap[Symbol.iterator]();
var rowEntry;
var halt = state.halt;
while (!state.halted && undefined !== (rowEntry = rowIt.fastNext())) {
var columnIt = rowEntry[1][Symbol.iterator]();
var columnEntry = void 0;
while (!state.halted &&
undefined !== (columnEntry = columnIt.fastNext())) {
f([rowEntry[0], columnEntry[0], columnEntry[1]], state.nextIndex(), halt);
}
}
};
TableNonEmpty.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();
};
TableNonEmpty.prototype.filterRows = function (pred, options) {
if (options === void 0) { options = {}; }
var _a = options.negate, negate = _a === void 0 ? false : _a;
var newSize = 0;
var newRowMap = this.rowMap.filter(function (e, i, halt) {
var result = pred(e, i, halt);
if (result !== negate)
newSize += e[1].size;
return result;
});
return this.copyE(newRowMap, newSize);
};
TableNonEmpty.prototype.mapValues = function (mapFun) {
return this.copy(this.rowMap.mapValues(function (row, r) {
return row.mapValues(function (v, c) { return mapFun(v, r, c); });
}), this.size);
};
TableNonEmpty.prototype.toArray = function () {
var result = [];
var rowIt = this.rowMap.stream()[Symbol.iterator]();
var rowEntry;
while (undefined !== (rowEntry = rowIt.fastNext())) {
var columnIt = rowEntry[1].stream()[Symbol.iterator]();
var columnEntry = void 0;
while (undefined !== (columnEntry = columnIt.fastNext())) {
result.push([rowEntry[0], columnEntry[0], columnEntry[1]]);
}
}
return result;
};
TableNonEmpty.prototype.toString = function () {
return this.stream().join({
start: "".concat(this.context.typeTag, "("),
sep: ", ",
end: ")",
valueToString: function (entry) { return "[".concat(entry[0], ", ").concat(entry[1], "] -> ").concat(entry[2]); },
});
};
TableNonEmpty.prototype.toJSON = function () {
return {
dataType: this.context.typeTag,
value: this.rowMap
.stream()
.map(function (entry) { return [entry[0], entry[1].toJSON().value]; })
.toArray(),
};
};
TableNonEmpty.prototype.toBuilder = function () {
return this.context.createBuilder(this);
};
return TableNonEmpty;
}(map_custom_1.NonEmptyBase));
exports.TableNonEmpty = TableNonEmpty;
var TableBuilder = /** @class */ (function () {
function TableBuilder(context, source) {
var _this = this;
this.context = context;
this.source = source;
//implements TableBase.Builder<R, C, V>
this._lock = 0;
this._size = 0;
this.get = function (row, column, otherwise) {
if (undefined !== _this.source) {
return _this.source.get(row, column, otherwise);
}
var token = Symbol();
var result = _this.rowMap.get(row, token);
if (token === result)
return (0, common_1.OptLazy)(otherwise);
return result.get(column, otherwise);
};
// prettier-ignore
this.getRow = function (row) {
if (undefined !== _this.source)
return _this.source.getRow(row);
var token = Symbol();
var result = _this.rowMap.get(row, token);
if (token === result)
return _this.context.columnContext.empty();
return result.build();
};
this.hasValueAt = function (row, column) {
if (undefined !== _this.source)
return _this.source.hasValueAt(row, column);
var token = Symbol();
return token !== _this.get(row, column, token);
};
// prettier-ignore
this.hasRowKey = function (row) {
var _a, _b;
return (_b = (_a = _this.source) === null || _a === void 0 ? void 0 : _a.hasRowKey(row)) !== null && _b !== void 0 ? _b : _this.rowMap.hasKey(row);
};
this.set = function (row, column, value) {
_this.checkLock();
var columnBuilder = undefined;
_this.rowMap.modifyAt(row, {
ifNew: function () {
columnBuilder = _this.context.columnContext.builder();
return columnBuilder;
},
ifExists: function (b) {
columnBuilder = b;
return b;
},
});
var changed = true;
columnBuilder.modifyAt(column, {
ifNew: function () {
_this._size++;
return value;
},
ifExists: function (currentValue) {
if (Object.is(currentValue, value))
changed = false;
return value;
},
});
if (changed)
_this.source = undefined;
return changed;
};
this.addEntry = function (entry) {
return _this.set(entry[0], entry[1], entry[2]);
};
this.addEntries = function (source) {
_this.checkLock();
return stream_1.Stream.applyFilter(source, { pred: _this.set }).count() > 0;
};
this.remove = function (row, column, otherwise) {
_this.checkLock();
var columnMap = _this.rowMap.get(row);
if (undefined === columnMap)
return (0, common_1.OptLazy)(otherwise);
if (!_this.context.columnContext.isValidKey(column)) {
return (0, common_1.OptLazy)(otherwise);
}
var removedValue = base_1.Token;
columnMap.modifyAt(column, {
ifExists: function (currentValue, remove) {
removedValue = currentValue;
_this._size--;
return remove;
},
});
if (columnMap.isEmpty)
_this.rowMap.removeKey(row);
if (base_1.Token === removedValue)
return (0, common_1.OptLazy)(otherwise);
_this.source = undefined;
return removedValue;
};
// prettier-ignore
this.removeRow = function (row) {
_this.checkLock();
if (!_this.context.rowContext.isValidKey(row))
return false;
return _this.rowMap.modifyAt(row, {
ifExists: function (row, remove) {
_this.source = undefined;
_this._size -= row.size;
return remove;
},
});
};
// prettier-ignore
this.removeRows = function (rows) {
_this.checkLock();
return stream_1.Stream.from(rows).filterPure({ pred: _this.removeRow }).count() > 0;
};
this.removeEntries = function (entries) {
_this.checkLock();
var notFound = Symbol();
return (stream_1.Stream.applyMap(entries, _this.remove, notFound).countElement(notFound, {
negate: true,
}) > 0);
};
this.modifyAt = function (row, column, options) {
_this.checkLock();
var changed = false;
_this.rowMap.modifyAt(row, {
ifNew: function (none) {
var ifNew = options.ifNew;
if (undefined === ifNew) {
return none;
}
var newValue = (0, common_1.OptLazyOr)(ifNew, none);
if (newValue === none) {
return none;
}
var rowMap = _this.context.columnContext.builder();
rowMap.set(column, newValue);
changed = true;
_this._size++;
return rowMap;
},
ifExists: function (curMap, remove) {
var preSize = curMap.size;
changed = curMap.modifyAt(column, options);
if (changed) {
var postSize = curMap.size;
_this._size += postSize - preSize;
if (postSize <= 0) {
return remove;
}
}
return curMap;
},
});
if (changed) {
_this.source = undefined;
}
return changed;
};
// prettier-ignore
this.updateAt = function (row, column, update, otherwise) {
_this.checkLock();
var oldValue;
var found = false;
_this.modifyAt(row, column, {
ifExists: function (value) {
oldValue = value;
found = true;
return (0, common_1.Update)(value, update);
},
});
if (!found)
return (0, common_1.OptLazy)(otherwise);
_this.source = undefined;
return oldValue;
};
this.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._lock++;
if (undefined !== _this.source) {
_this.source.forEach(f, { state: state });
}
else {
var halt_1 = state.halt;
_this.rowMap.forEach(function (_a, _, rowHalt) {
var _b = tslib_1.__read(_a, 2), rowKey = _b[0], column = _b[1];
column.forEach(function (_a, _, columnHalt) {
var _b = tslib_1.__read(_a, 2), columnKey = _b[0], value = _b[1];
f([rowKey, columnKey, value], state.nextIndex(), halt_1);
if (state.halted) {
rowHalt();
columnHalt();
}
});
});
}
_this._lock--;
};
this.build = function () {
if (undefined !== _this.source)
return _this.source;
if (_this.isEmpty)
return _this.context.empty();
return _this.context.createNonEmpty(_this.rowMap
.buildMapValues(function (row) { return row.build().assumeNonEmpty(); })
.assumeNonEmpty(), _this.size);
};
// prettier-ignore
this.buildMapValues = function (mapFun) {
if (undefined !== _this.source)
return _this.source.mapValues(mapFun);
if (_this.isEmpty)
return _this.context.empty();
var newRowMap = _this.rowMap
.buildMapValues(function (row, rowKey) {
return row
.buildMapValues(function (value, columnKey) {
return mapFun(value, rowKey, columnKey);
})
.assumeNonEmpty();
})
.assumeNonEmpty();
return _this.context.createNonEmpty(newRowMap, _this.size);
};
if (undefined !== source)
this._size = source.size;
}
Object.defineProperty(TableBuilder.prototype, "rowMap", {
get: function () {
if (undefined === this._rowMap) {
if (undefined === this.source) {
this._rowMap = this.context.rowContext.builder();
}
else {
this._rowMap = this.source.rowMap
.mapValues(function (v) { return v.toBuilder(); })
.toBuilder();
}
}
return this._rowMap;
},
enumerable: false,
configurable: true
});
TableBuilder.prototype.checkLock = function () {
if (this._lock)
base_1.RimbuError.throwModifiedBuilderWhileLoopingOverItError();
};
Object.defineProperty(TableBuilder.prototype, "size", {
get: function () {
return this._size;
},
enumerable: false,
configurable: true
});
Object.defineProperty(TableBuilder.prototype, "isEmpty", {
get: function () {
return this.size === 0;
},
enumerable: false,
configurable: true
});
Object.defineProperty(TableBuilder.prototype, "amountRows", {
get: function () {
var _a, _b;
return (_b = (_a = this.source) === null || _a === void 0 ? void 0 : _a.amountRows) !== null && _b !== void 0 ? _b : this.rowMap.size;
},
enumerable: false,
configurable: true
});
return TableBuilder;
}());
exports.TableBuilder = TableBuilder;
var TableContext = /** @class */ (function () {
function TableContext(typeTag, rowContext, columnContext) {
var _this = this;
this.typeTag = typeTag;
this.rowContext = rowContext;
this.columnContext = columnContext;
this._empty = Object.freeze(new TableEmpty(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 TableBuilder(_this);
};
this.reducer = function (source) {
return stream_1.Reducer.create(function () {
return undefined === source
? _this.builder()
: _this.from(source).toBuilder();
}, function (builder, entry) {
builder.addEntry(entry);
return builder;
}, function (builder) { return builder.build(); });
};
}
Object.defineProperty(TableContext.prototype, "_types", {
get: function () {
return undefined;
},
enumerable: false,
configurable: true
});
TableContext.prototype.isNonEmptyInstance = function (source) {
return source instanceof TableNonEmpty;
};
TableContext.prototype.createNonEmpty = function (rowMap, size) {
return new TableNonEmpty(this, rowMap, size);
};
TableContext.prototype.createBuilder = function (source) {
return new TableBuilder(this, source);
};
return TableContext;
}());
exports.TableContext = TableContext;
//# sourceMappingURL=base.cjs.map