UNPKG

mute-structs

Version:

NodeJS module providing an implementation of the LogootSplit CRDT algorithm

178 lines (174 loc) 6.79 kB
/* This file is part of MUTE-structs. Copyright (C) 2017 Matthieu Nicolas, Victorien Elvinger This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ import { isObject } from "./data-validation"; import { isSorted } from "./helpers"; import { Identifier } from "./identifier"; import { isInt32 } from "./int32"; /** * Define an interval between two identifiers sharing the same base */ var IdentifierInterval = /** @class */ (function () { // Creation function IdentifierInterval(idBegin, end) { console.assert(isInt32(end), "end ∈ int32"); console.assert(idBegin.lastOffset <= end, "idBegin must be less than or equal to idEnd"); this.idBegin = idBegin; this.end = end; } IdentifierInterval.fromPlain = function (o) { if (isObject(o) && isInt32(o.end)) { var idBegin = Identifier.fromPlain(o.idBegin); if (idBegin !== null && idBegin.lastOffset <= o.end) { return new IdentifierInterval(idBegin, o.end); } } return null; }; /** * Merge as much as possible Identifiers contained into an array into IdentifierIntervals * * @param {Identifier[]} ids The array of Identifiers * @return {IdentifierInterval[]} The corresponding array of IdentifierIntervals */ IdentifierInterval.mergeIdsIntoIntervals = function (ids) { var compareIdsFn = function (id, other) { return id.compareTo(other); }; console.assert(isSorted(ids, compareIdsFn), "The array should be sorted"); var res = []; if (ids.length > 0) { var idBegin = ids[0]; for (var i = 1; i < ids.length; i++) { var prevId = ids[i - 1]; var id = ids[i]; if (!prevId.equalsBase(id) || prevId.lastOffset + 1 !== id.lastOffset) { var idInterval = new IdentifierInterval(idBegin, prevId.lastOffset); res.push(idInterval); idBegin = id; } } var lastId = ids[ids.length - 1]; var lastIdInterval = new IdentifierInterval(idBegin, lastId.lastOffset); res.push(lastIdInterval); } return res; }; Object.defineProperty(IdentifierInterval.prototype, "begin", { /** * Shortcut to retrieve the offset of the last tuple of idBegin * This offset also corresponds to the beginning of the interval * * @return {number} The offset */ get: function () { return this.idBegin.lastOffset; }, enumerable: true, configurable: true }); Object.defineProperty(IdentifierInterval.prototype, "idEnd", { /** * Shortcut to retrieve the last identifier of the interval * * @return {Identifier} The last identifier of the interval */ get: function () { return this.getBaseId(this.end); }, enumerable: true, configurable: true }); Object.defineProperty(IdentifierInterval.prototype, "length", { /** * Shortcut to compute the length of the interval * * @return {number} The length */ get: function () { return this.end - this.begin + 1; }, enumerable: true, configurable: true }); Object.defineProperty(IdentifierInterval.prototype, "base", { get: function () { return this.idBegin.base; }, enumerable: true, configurable: true }); Object.defineProperty(IdentifierInterval.prototype, "dot", { get: function () { return this.idBegin.dot; }, enumerable: true, configurable: true }); IdentifierInterval.prototype.equals = function (aOther) { return this.idBegin.equals(aOther.idBegin) && this.begin === aOther.begin && this.end === aOther.end; }; /** * Compute the union between this interval and [aBegin, aEnd] * * @param {number} aBegin * @param {number} aEnd * @return {IdentifierInterval} this U [aBegin, aEnd] */ IdentifierInterval.prototype.union = function (aBegin, aEnd) { console.assert(isInt32(aBegin), "aBegin ∈ int32"); console.assert(isInt32(aEnd), "aEnd ∈ int32"); var minBegin = Math.min(this.begin, aBegin); var maxEnd = Math.max(this.end, aEnd); var newIdBegin = Identifier.fromBase(this.idBegin, minBegin); return new IdentifierInterval(newIdBegin, maxEnd); }; /** * Check if the provided identifier belongs to this interval * * @param {Identifier} id * @return {boolean} Does the identifier belongs to this interval */ IdentifierInterval.prototype.containsId = function (id) { return this.idBegin.compareTo(id) === -1 /* Less */ && this.idEnd.compareTo(id) === 1 /* Greater */; }; /** * Retrieve a identifier from the interval from its offset * * @param {number} offset The offset of the identifier * @return {Identifier} The identifier */ IdentifierInterval.prototype.getBaseId = function (offset) { console.assert(isInt32(offset), "offset ∈ int32"); console.assert(this.begin <= offset && offset <= this.end, "offset must be included in the interval"); return Identifier.fromBase(this.idBegin, offset); }; IdentifierInterval.prototype.digest = function () { // '| 0' converts to 32bits integer return (this.idBegin.digest() * 17 + this.end) | 0; }; IdentifierInterval.prototype.toIds = function () { var res = []; for (var i = this.begin; i <= this.end; i++) { res.push(Identifier.fromBase(this.idBegin, i)); } return res; }; IdentifierInterval.prototype.toString = function () { return "IdInterval[" + this.idBegin.tuples.join(",") + " .. " + this.end + "]"; }; return IdentifierInterval; }()); export { IdentifierInterval }; //# sourceMappingURL=identifierinterval.js.map