@graffy/common
Version:
Common libraries that used by various Graffy modules.
193 lines (157 loc) • 5.53 kB
JavaScript
;
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 _getIterator2 = _interopRequireDefault(require("@babel/runtime-corejs3/core-js/get-iterator"));
var _isArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/array/is-array"));
var _node2 = require("../node");
var _step = require("./step");
var _path = require("../path");
var _merge = _interopRequireDefault(require("./merge"));
var _add = _interopRequireDefault(require("./add"));
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 = currentQuery, _isArray = (0, _isArray2["default"])(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator2["default"])(_iterator);;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var queryNode = _ref;
if ((0, _node2.isRange)(queryNode)) {
sliceRange(graph, queryNode, result);
} else {
var key = queryNode.key;
index = (0, _node2.getIndex)(graph, key, index); // console.log('Index', graph, key, index);
sliceNode(graph[index], queryNode, result);
}
}
currentQuery = result.linked;
delete result.linked;
}
delete result.root;
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.
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 _slice = slice(graph.children, query.children, root),
known = _slice.known,
unknown = _slice.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) && (0, _node2.isBranch)(query)) {
result.addKnown(graph);
result.addLinked((0, _path.wrap)(query.children, graph.path, version));
} 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');
} else if ((0, _node2.isRange)(graph)) {
result.addKnown({
key: key,
end: key,
version: graph.version
});
} else {
result.addKnown(graph);
}
}
function sliceRange(graph, query, result) {
var key = query.key,
end = query.end,
count = query.count,
version = query.version;
if (count > 0) {
for (var i = (0, _node2.getIndex)(graph, key); key <= end && count > 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);
count--;
}
key = (0, _step.keyAfter)(node.end || node.key);
}
} else {
for (var _i2 = (0, _node2.getLastIndex)(graph, end) - 1; end >= key && count < 0; _i2--) {
var _node = graph[_i2];
if (!_node || end > (_node.end || _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: end
}), result);
count++;
}
end = (0, _step.keyBefore)(_node.key);
}
}
if (count && key < end) {
var unknown = (0, _extends2["default"])({}, query, {
key: key,
end: end,
count: count
});
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
});
}