@graffy/common
Version:
Common libraries that used by various Graffy modules.
218 lines (173 loc) • 7.92 kB
JavaScript
var _sliceInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/slice");
var _Array$from = require("@babel/runtime-corejs3/core-js-stable/array/from");
var _Symbol = require("@babel/runtime-corejs3/core-js-stable/symbol");
var _getIteratorMethod = require("@babel/runtime-corejs3/core-js/get-iterator-method");
var _Array$isArray = require("@babel/runtime-corejs3/core-js-stable/array/is-array");
var _getIterator = require("@babel/runtime-corejs3/core-js/get-iterator");
var _bindInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/bind");
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = slice;
exports.sliceRange = sliceRange;
var _extends2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/extends"));
var _node2 = require("../node");
var _step2 = require("./step");
var _path = require("../path");
var _merge = _interopRequireDefault(require("./merge"));
var _add = _interopRequireDefault(require("./add"));
var _testing = require("@graffy/testing");
function _createForOfIteratorHelperLoose(o, allowArrayLike) { var _context2; var it; if (typeof _Symbol === "undefined" || _getIteratorMethod(o) == null) { if (_Array$isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } it = _getIterator(o); return _bindInstanceProperty(_context2 = it.next).call(_context2, it); }
function _unsupportedIterableToArray(o, minLen) { var _context; if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = _sliceInstanceProperty(_context = Object.prototype.toString.call(o)).call(_context, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
var Result = /*#__PURE__*/function () {
function Result(root) {
// When linked queries are added, they are forwarded to the root.
this.root = root || this;
}
var _proto = Result.prototype;
_proto.addKnown = function addKnown(node) {
this.known = this.known || [];
(0, _merge.default)(this.known, [node]);
};
_proto.addUnknown = function addUnknown(node) {
this.unknown = this.unknown || [];
this.unknown.push(node);
};
_proto.addLinked = function addLinked(children) {
if (this.root !== this) return this.root.addLinked(children);
this.linked = this.linked || [];
(0, _add.default)(this.linked, children);
};
return Result;
}();
function slice(graph, query, root) {
var result = new Result(root);
var currentQuery = query;
while (currentQuery) {
var index = 0;
for (var _iterator = _createForOfIteratorHelperLoose(currentQuery), _step; !(_step = _iterator()).done;) {
var queryNode = _step.value;
if ((0, _node2.isRange)(queryNode)) {
sliceRange(graph, queryNode, result);
} else {
var key = queryNode.key;
index = (0, _node2.findFirst)(graph, key, index); // console.log('Index', graph, key, index);
sliceNode(graph[index], queryNode, result);
}
}
currentQuery = root ? undefined : result.linked;
delete result.linked;
}
delete result.root; // console.log(
// 'slice:\n' + format(graph) + format(query) + format(result.known),
// );
return result;
}
function sliceNode(graph, query, result) {
var key = query.key,
version = query.version;
var root = result.root; // console.log('Slicing', graph, query);
if (!graph || graph.key > key || (0, _node2.isOlder)(graph, version)) {
// The node found doesn't match the query or it's too old.
result.addUnknown(query);
} else if ((0, _node2.isRange)(graph)) {
// The graph is indicating that this value was deleted.
if ((0, _node2.isBranch)(query)) {
var _slice = slice([{
key: '',
end: "\uFFFF",
version: graph.version
}], query.children),
known = _slice.known;
result.addKnown({
key: key,
version: graph.version,
children: known
});
} else {
result.addKnown({
key: key,
end: key,
version: graph.version
});
}
} else if ((0, _node2.isBranch)(graph) && (0, _node2.isBranch)(query)) {
// Both sides are branches; recurse into them.
var _slice2 = slice(graph.children, query.children, root),
_known = _slice2.known,
unknown = _slice2.unknown;
if (_known) result.addKnown((0, _extends2.default)({}, graph, {
children: _known
}));
if (unknown) result.addUnknown((0, _extends2.default)({}, query, {
children: unknown
}));
} else if ((0, _node2.isLink)(graph)) {
result.addKnown(graph);
result.addLinked((0, _node2.isBranch)(query) ? (0, _path.wrap)(query.children, graph.path, version) : (0, _path.wrapValue)(query.value, graph.path, version));
} else if ((0, _node2.isBranch)(graph) && query.options && query.options.subtree) {
// This option allows a query to say "give me the subtree under this"
// without knowing specifically what's available. If using this, the
// value of "unknown" is no longer reliable. It is intended for use in
// optimistic updates.
result.addKnown(graph);
} else if ((0, _node2.isBranch)(graph) || (0, _node2.isBranch)(query)) {
// One side is a branch while the other is a leaf; throw error.
throw new Error('slice.leaf_branch_mismatch:' + (0, _testing.format)(graph) + '\n' + (0, _testing.format)(query));
} else {
result.addKnown(graph);
}
}
function sliceRange(graph, query, result) {
var key = query.key,
end = query.end,
_query$limit = query.limit,
limit = _query$limit === void 0 ? Infinity : _query$limit,
version = query.version;
var step = key < end ? 1 : -1;
if (key < end) {
for (var i = (0, _node2.findFirst)(graph, key); key <= end && limit > 0; i++) {
var node = graph[i];
if (!node || key < node.key || (0, _node2.isOlder)(node, version)) break;
if ((0, _node2.isRange)(node)) {
result.addKnown(getOverlap(node, key, end));
} else {
sliceNode(node, (0, _extends2.default)({}, query, {
key: key
}), result);
limit--;
}
key = (0, _step2.keyAfter)(node.end || node.key);
}
} else {
for (var _i = (0, _node2.findLast)(graph, key) - 1; key >= end && limit > 0; _i--) {
var _node = graph[_i];
if (!_node || key > (_node.end || _node.key) || (0, _node2.isOlder)(_node, version)) break;
if ((0, _node2.isRange)(_node)) {
result.addKnown(getOverlap(_node, end, key));
} else {
sliceNode(_node, (0, _extends2.default)({}, query, {
key: key
}), result);
limit--;
}
key = (0, _step2.keyBefore)(_node.key);
}
}
if (limit && (step < 0 ? key > end : key < end)) {
var unknown = (0, _extends2.default)({}, query, {
key: key,
end: end,
limit: limit
});
result.addUnknown(unknown);
}
}
function getOverlap(node, key, end) {
if (node.key >= key && node.end <= end) return node;
return (0, _extends2.default)({}, node, {
key: node.key > key ? node.key : key,
end: node.end < end ? node.end : end
});
}
;