@fluid-experimental/tree 0.59.3003 → 0.59.4000-71128
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Forest.js +1 -1
- package/dist/Forest.js.map +1 -1
- package/dist/SharedTree.d.ts +89 -30
- package/dist/SharedTree.d.ts.map +1 -1
- package/dist/SharedTree.js +93 -58
- package/dist/SharedTree.js.map +1 -1
- package/dist/SharedTreeEncoder.d.ts +1 -1
- package/dist/SharedTreeEncoder.d.ts.map +1 -1
- package/dist/SharedTreeEncoder.js.map +1 -1
- package/dist/id-compressor/IdCompressor.d.ts +19 -45
- package/dist/id-compressor/IdCompressor.d.ts.map +1 -1
- package/dist/id-compressor/IdCompressor.js +151 -151
- package/dist/id-compressor/IdCompressor.js.map +1 -1
- package/dist/id-compressor/SessionIdNormalizer.d.ts +1 -16
- package/dist/id-compressor/SessionIdNormalizer.d.ts.map +1 -1
- package/dist/id-compressor/SessionIdNormalizer.js +23 -21
- package/dist/id-compressor/SessionIdNormalizer.js.map +1 -1
- package/dist/id-compressor/persisted-types/0.0.1.d.ts +23 -4
- package/dist/id-compressor/persisted-types/0.0.1.d.ts.map +1 -1
- package/dist/id-compressor/persisted-types/0.0.1.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/lib/Forest.js +1 -1
- package/lib/Forest.js.map +1 -1
- package/lib/SharedTree.d.ts +89 -30
- package/lib/SharedTree.d.ts.map +1 -1
- package/lib/SharedTree.js +94 -59
- package/lib/SharedTree.js.map +1 -1
- package/lib/SharedTreeEncoder.d.ts +1 -1
- package/lib/SharedTreeEncoder.d.ts.map +1 -1
- package/lib/SharedTreeEncoder.js.map +1 -1
- package/lib/id-compressor/IdCompressor.d.ts +19 -45
- package/lib/id-compressor/IdCompressor.d.ts.map +1 -1
- package/lib/id-compressor/IdCompressor.js +152 -152
- package/lib/id-compressor/IdCompressor.js.map +1 -1
- package/lib/id-compressor/SessionIdNormalizer.d.ts +1 -16
- package/lib/id-compressor/SessionIdNormalizer.d.ts.map +1 -1
- package/lib/id-compressor/SessionIdNormalizer.js +23 -21
- package/lib/id-compressor/SessionIdNormalizer.js.map +1 -1
- package/lib/id-compressor/persisted-types/0.0.1.d.ts +23 -4
- package/lib/id-compressor/persisted-types/0.0.1.d.ts.map +1 -1
- package/lib/id-compressor/persisted-types/0.0.1.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/test/IdCompressor.perf.tests.js +47 -67
- package/lib/test/IdCompressor.perf.tests.js.map +1 -1
- package/lib/test/IdCompressor.tests.js +196 -101
- package/lib/test/IdCompressor.tests.js.map +1 -1
- package/lib/test/Summary.tests.d.ts +0 -1
- package/lib/test/Summary.tests.d.ts.map +1 -1
- package/lib/test/Summary.tests.js +0 -3
- package/lib/test/Summary.tests.js.map +1 -1
- package/lib/test/Virtualization.tests.js +0 -4
- package/lib/test/Virtualization.tests.js.map +1 -1
- package/lib/test/fuzz/SharedTreeFuzzTests.d.ts.map +1 -1
- package/lib/test/fuzz/SharedTreeFuzzTests.js +3 -1
- package/lib/test/fuzz/SharedTreeFuzzTests.js.map +1 -1
- package/lib/test/utilities/IdCompressorTestUtilities.d.ts +14 -7
- package/lib/test/utilities/IdCompressorTestUtilities.d.ts.map +1 -1
- package/lib/test/utilities/IdCompressorTestUtilities.js +40 -20
- package/lib/test/utilities/IdCompressorTestUtilities.js.map +1 -1
- package/lib/test/utilities/SharedTreeTests.d.ts.map +1 -1
- package/lib/test/utilities/SharedTreeTests.js +27 -51
- package/lib/test/utilities/SharedTreeTests.js.map +1 -1
- package/lib/test/utilities/SharedTreeVersioningTests.d.ts.map +1 -1
- package/lib/test/utilities/SharedTreeVersioningTests.js +19 -19
- package/lib/test/utilities/SharedTreeVersioningTests.js.map +1 -1
- package/lib/test/utilities/SummaryLoadPerfTests.js +1 -1
- package/lib/test/utilities/SummaryLoadPerfTests.js.map +1 -1
- package/lib/test/utilities/TestCommon.d.ts +4 -0
- package/lib/test/utilities/TestCommon.d.ts.map +1 -1
- package/lib/test/utilities/TestCommon.js +6 -0
- package/lib/test/utilities/TestCommon.js.map +1 -1
- package/lib/test/utilities/TestUtilities.d.ts.map +1 -1
- package/lib/test/utilities/TestUtilities.js +4 -6
- package/lib/test/utilities/TestUtilities.js.map +1 -1
- package/package.json +24 -19
- package/src/Forest.ts +1 -1
- package/src/SharedTree.ts +195 -46
- package/src/SharedTreeEncoder.ts +1 -1
- package/src/id-compressor/IdCompressor.ts +171 -198
- package/src/id-compressor/SessionIdNormalizer.ts +29 -41
- package/src/id-compressor/persisted-types/0.0.1.ts +25 -4
- package/src/index.ts +4 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionIdNormalizer.d.ts","sourceRoot":"","sources":["../../src/id-compressor/SessionIdNormalizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"SessionIdNormalizer.d.ts","sourceRoot":"","sources":["../../src/id-compressor/SessionIdNormalizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAEhG,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,mBAAmB,CAAC,YAAY;IAkBzB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAjBpD,OAAO,CAAC,WAAW,CAA8C;IACjE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAcvB;gBAEkC,gBAAgB,UAAQ;IAE5D;;;OAGG;IACI,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,wBAAwB,GAAG,SAAS;IAqB1F;;OAEG;IACI,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,CAAC,iBAAiB,EAAE,YAAY,CAAC,GAAG,SAAS;IAoB5F;;;OAGG;IACI,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS;IAgBvE;;OAEG;IACI,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,wBAAwB,GAAG,SAAS;IAwBhF,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAQjC;;OAEG;IACI,cAAc,IAAI,iBAAiB,GAAG,SAAS;IAetD;;;;;;OAMG;IACI,UAAU,IAAI,iBAAiB;IA6BtC;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,WAAW,CAAC,UAAU,EAAE,iBAAiB,EAAE,SAAS,EAAE,iBAAiB,EAAE,WAAW,EAAE,YAAY,GAAG,IAAI;IAkDhH;;OAEG;IACK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,wBAAwB,CAAC;IAwBhE,SAAS,IAAI,6BAA6B;WAkBnC,WAAW,CAAC,YAAY,EACrC,UAAU,EAAE,6BAA6B,EACzC,cAAc,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,YAAY,GAC1D,mBAAmB,CAAC,YAAY,CAAC;IAuB7B,MAAM,CACZ,KAAK,EAAE,mBAAmB,CAAC,YAAY,CAAC,EACxC,mBAAmB,GAAE,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,KAAK,OAA2B,GACpF,OAAO;CA+BV"}
|
|
@@ -295,7 +295,7 @@ class SessionIdNormalizer {
|
|
|
295
295
|
}
|
|
296
296
|
}
|
|
297
297
|
serialize() {
|
|
298
|
-
const serialized = { localRanges: [] };
|
|
298
|
+
const serialized = { localRanges: [], nextLocalId: this.nextLocalId };
|
|
299
299
|
const localRanges = serialized.localRanges;
|
|
300
300
|
for (const [firstLocal, finalRanges] of this.idRanges.entries()) {
|
|
301
301
|
const [lastLocal, finalRangesTable] = finalRanges;
|
|
@@ -332,30 +332,32 @@ class SessionIdNormalizer {
|
|
|
332
332
|
}
|
|
333
333
|
idRanges.append(firstLocal, [lastLocal, finalRanges]);
|
|
334
334
|
}
|
|
335
|
+
normalizer.nextLocalId = serialized.nextLocalId;
|
|
335
336
|
return normalizer;
|
|
336
337
|
}
|
|
337
338
|
equals(other, compareRangeObjects = (a, b) => a === b) {
|
|
338
|
-
return this.
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
const rangeEquals = (finalRangeA, finalRangeB) => {
|
|
345
|
-
const [firstFinalA, lastFinalA, rangeObjectA] = finalRangeA;
|
|
346
|
-
const [firstFinalB, lastFinalB, rangeObjectB] = finalRangeB;
|
|
347
|
-
return (firstFinalA === firstFinalB &&
|
|
348
|
-
lastFinalA === lastFinalB &&
|
|
349
|
-
compareRangeObjects(rangeObjectA, rangeObjectB));
|
|
350
|
-
};
|
|
351
|
-
if (isSingleRange(finalRangesA) || isSingleRange(finalRangesB)) {
|
|
352
|
-
if (!isSingleRange(finalRangesA) || !isSingleRange(finalRangesB)) {
|
|
353
|
-
return false;
|
|
339
|
+
return (this.nextLocalId === other.nextLocalId &&
|
|
340
|
+
this.idRanges.equals(other.idRanges, (localRangeA, localRangeB) => {
|
|
341
|
+
const [lastLocalA, finalRangesA] = localRangeA;
|
|
342
|
+
const [lastLocalB, finalRangesB] = localRangeB;
|
|
343
|
+
if (finalRangesA === undefined || finalRangesB === undefined) {
|
|
344
|
+
return finalRangesA === finalRangesB;
|
|
354
345
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
346
|
+
const rangeEquals = (finalRangeA, finalRangeB) => {
|
|
347
|
+
const [firstFinalA, lastFinalA, rangeObjectA] = finalRangeA;
|
|
348
|
+
const [firstFinalB, lastFinalB, rangeObjectB] = finalRangeB;
|
|
349
|
+
return (firstFinalA === firstFinalB &&
|
|
350
|
+
lastFinalA === lastFinalB &&
|
|
351
|
+
compareRangeObjects(rangeObjectA, rangeObjectB));
|
|
352
|
+
};
|
|
353
|
+
if (isSingleRange(finalRangesA) || isSingleRange(finalRangesB)) {
|
|
354
|
+
if (!isSingleRange(finalRangesA) || !isSingleRange(finalRangesB)) {
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
return rangeEquals(finalRangesA, finalRangesB);
|
|
358
|
+
}
|
|
359
|
+
return lastLocalA === lastLocalB && finalRangesA.equals(finalRangesB, rangeEquals);
|
|
360
|
+
}));
|
|
359
361
|
}
|
|
360
362
|
}
|
|
361
363
|
exports.SessionIdNormalizer = SessionIdNormalizer;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionIdNormalizer.js","sourceRoot":"","sources":["../../src/id-compressor/SessionIdNormalizer.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable @typescript-eslint/restrict-plus-operands */\n\nimport { assert, compareFiniteNumbers, compareFiniteNumbersReversed, fail, Mutable } from '../Common';\nimport { FinalCompressedId, LocalCompressedId, SessionSpaceCompressedId } from '../Identifiers';\nimport { AppendOnlyDoublySortedMap } from './AppendOnlySortedMap';\n\n/**\n * Maps IDs created by a session between their local and final forms (i.e. normalization). These IDs are in a contiguous range.\n * The local and final forms of IDs made by a session can be thought of as two equal-length sparse arrays, aligned such\n * that normalizeLocalToFinal(locals[i]) === finals[i] and vice versa.\n * Below is an example to illustrate how various mappings can arise:\n *\n * +- Creation Index\n * / +- Locals\n * / / +- Finals\n * / / /\n * ---+-----+----\n * 0 | -1 | 0 -|___ Two IDs are allocated as locals since no cluster exists. A new cluster is created when acked.\n * 1 | -2 | 1 -|\n * 2 | | 2 -|\n * 3 | | 3 --|-- Three more IDs are allocated as finals eagerly since a cluster exists with available capacity.\n * 4 | | 4 -|\n * 5 | -6 | 10 ----- One ID is allocated as a local (it overflows the existing cluster) and a new cluster is created after ack.\n * 6 | | 11 ----- One ID is allocated as a final eagerly into the existing cluster.\n * 7 | -8 | 12 ----- A local ID with an override is allocated. The override forces it to be a local ID.\n * 8 | | 13\n * 9 | | 14\n * 10 | -11 | ----- A local ID is allocated. It has no corresponding final ID since it has not been acked.\n *\n * Note that in this example, some IDs (those at indices 2, 3, 4, 6, 8, and 9) have no local form. The ID at index 10 has no final form.\n * These kinds of \"gaps\" occur due to the timing of allocation calls on the client and how they relate to finalization/cluster creation,\n * which depends on receiving an ack/sequence number from the server. Given this context, \"session space\" can be thought of as:\n *\n * \t\tfor each index in the range of IDs created by a session:\n * \t\t\tthe local form if it exists, otherwise the final form\n *\n * This class is designed to efficiently build and query these mappings by leveraging the facts that much of the range (in both local and\n * final space) is uninterrupted by \"gaps\" and can be compactly represented by a (first, last) pair and is easily binary searched for\n * normalization between local and final space.\n */\nexport class SessionIdNormalizer<TRangeObject> {\n\tprivate nextLocalId: LocalCompressedId = -1 as LocalCompressedId;\n\tprivate readonly idRanges: AppendOnlyDoublySortedMap<\n\t\tLocalCompressedId,\n\t\t[lastLocal: LocalCompressedId, finalRanges: FinalRanges<TRangeObject> | undefined],\n\t\tFinalCompressedId\n\t> = new AppendOnlyDoublySortedMap(\n\t\tcompareFiniteNumbersReversed,\n\t\t([_, finalRanges]) => {\n\t\t\tif (finalRanges !== undefined) {\n\t\t\t\tconst first = getFirstRange(finalRanges);\n\t\t\t\treturn extractFirstFinalFromRange(first);\n\t\t\t}\n\t\t\treturn Number.POSITIVE_INFINITY as FinalCompressedId;\n\t\t},\n\t\tcompareFiniteNumbers\n\t);\n\n\tpublic constructor(private readonly expensiveAsserts = false) {}\n\n\t/**\n\t * Converts the final ID to its session-space representation.\n\t * This will be the corresponding local if a local form exists, and `finalId` otherwise.\n\t */\n\tpublic getSessionSpaceId(finalId: FinalCompressedId): SessionSpaceCompressedId | undefined {\n\t\tconst localRange = this.idRanges.getPairOrNextLowerByValue(finalId);\n\t\tif (localRange !== undefined) {\n\t\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\t\tconst finalRange = getPairOrNextLowerByValue(firstLocal, finalRanges, finalId);\n\t\t\tif (finalRange !== undefined) {\n\t\t\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\t\t\tif (finalId <= lastFinal) {\n\t\t\t\t\tconst localRangeDelta = alignedLocal - lastLocal;\n\t\t\t\t\tconst finalDelta = finalId - firstFinal;\n\t\t\t\t\tif (finalDelta <= localRangeDelta) {\n\t\t\t\t\t\treturn (alignedLocal - finalDelta) as LocalCompressedId;\n\t\t\t\t\t}\n\t\t\t\t\t// `finalId` was an eagerly generated final ID\n\t\t\t\t\treturn finalId as SessionSpaceCompressedId;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Converts the local ID to its corresponding final ID, if one exists.\n\t */\n\tpublic getFinalId(localId: LocalCompressedId): [FinalCompressedId, TRangeObject] | undefined {\n\t\tconst localRange =\n\t\t\tthis.idRanges.getPairOrNextLower(localId) ?? fail('Local ID was never recorded with this normalizer.');\n\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\tif (localId < lastLocal) {\n\t\t\tfail('Local ID was never recorded with this normalizer.');\n\t\t}\n\t\tconst finalRange = getPairOrNextLower(firstLocal, finalRanges, localId);\n\t\tif (finalRange !== undefined) {\n\t\t\tconst [alignedLocal, [firstFinal, lastFinal, rangeObject]] = finalRange;\n\t\t\tconst rangeDelta = lastFinal - firstFinal;\n\t\t\tconst localDelta = alignedLocal - localId;\n\t\t\tif (localDelta <= rangeDelta) {\n\t\t\t\t// Local is within a range segment that has a corresponding final\n\t\t\t\treturn [(firstFinal + localDelta) as FinalCompressedId, rangeObject];\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Returns the index of the supplied session-space ID in the total range of IDs created by the session, if the ID was created\n\t * by the session for this `SessionIdNormalizer`.\n\t */\n\tpublic getCreationIndex(finalId: FinalCompressedId): number | undefined {\n\t\tconst localRange = this.idRanges.getPairOrNextLowerByValue(finalId);\n\t\tif (localRange !== undefined) {\n\t\t\tconst [firstLocal, [_, finalRanges]] = localRange;\n\t\t\tconst finalRange = getPairOrNextLowerByValue(firstLocal, finalRanges, finalId);\n\t\t\tif (finalRange !== undefined) {\n\t\t\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\t\t\tif (finalId <= lastFinal) {\n\t\t\t\t\tconst finalDelta = finalId - firstFinal;\n\t\t\t\t\treturn -alignedLocal - 1 + finalDelta;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Returns the session-space ID at the supplied creation index, if one exists.\n\t */\n\tpublic getIdByCreationIndex(index: number): SessionSpaceCompressedId | undefined {\n\t\tconst localByIndex = -(index + 1) as LocalCompressedId;\n\t\tconst localRange = this.idRanges.getPairOrNextLower(localByIndex);\n\t\tif (localRange === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\tif (localByIndex >= lastLocal) {\n\t\t\treturn localByIndex;\n\t\t}\n\t\tconst finalRange =\n\t\t\tgetPairOrNextLower(firstLocal, finalRanges, localByIndex) ??\n\t\t\tfail('Final ranges not aligned with owning local range.');\n\n\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\tconst localDelta = alignedLocal - localByIndex;\n\t\tconst finalId = firstFinal + localDelta;\n\t\tif (finalId <= lastFinal) {\n\t\t\t// `finalId` was an eagerly generated final ID\n\t\t\treturn finalId as SessionSpaceCompressedId;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate static makeFinalRangesMap<TRangeObject>(): FinalRangesMap<TRangeObject> {\n\t\treturn new AppendOnlyDoublySortedMap(\n\t\t\tcompareFiniteNumbersReversed,\n\t\t\textractFirstFinalFromRange,\n\t\t\tcompareFiniteNumbers\n\t\t);\n\t}\n\n\t/**\n\t * Returns the last final ID known to this normalizer.\n\t */\n\tpublic getLastFinalId(): FinalCompressedId | undefined {\n\t\tconst lastIndex = this.idRanges.size - 1;\n\t\tconst secondToLast = Math.max(0, lastIndex - 1);\n\t\tfor (let i = lastIndex; i >= secondToLast; i--) {\n\t\t\tconst localRange = this.idRanges.getAtIndex(i);\n\t\t\tif (localRange !== undefined) {\n\t\t\t\tconst finalRanges = localRange[1][1];\n\t\t\t\tif (finalRanges !== undefined) {\n\t\t\t\t\treturn getLastRange(finalRanges)[1];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Registers and returns the next ID in local space with this normalizer. An example:\n\t *\n\t * Locals: [-1, -2, X, X]\n\t * Finals: [ 0, 1, 2, 3]\n\t * In this scenario, a call to this method would generate and return -5.\n\t */\n\tpublic addLocalId(): LocalCompressedId {\n\t\tconst localId = this.nextLocalId-- as LocalCompressedId;\n\t\tconst lastLocalRange = this.idRanges.last();\n\t\tif (lastLocalRange !== undefined) {\n\t\t\tconst lastLocal = lastLocalRange[1][0];\n\t\t\tif (localId === lastLocal - 1) {\n\t\t\t\t// New local simply expands the last local range tracked\n\t\t\t\tlastLocalRange[1][0] = localId;\n\t\t\t\treturn localId;\n\t\t\t}\n\t\t}\n\n\t\tif (this.expensiveAsserts) {\n\t\t\tif (lastLocalRange === undefined) {\n\t\t\t\tassert(localId === -1, 'Local ID space must start at -1.');\n\t\t\t} else {\n\t\t\t\tconst [firstLocal, [_, finalRanges]] = lastLocalRange;\n\t\t\t\tlet finalDelta = 0;\n\t\t\t\tfor (const [_, [firstFinal, lastFinal]] of entries(firstLocal, finalRanges)) {\n\t\t\t\t\tfinalDelta += lastFinal - firstFinal + 1;\n\t\t\t\t}\n\t\t\t\tassert(localId === firstLocal - finalDelta, 'Local ID space must be contiguous.');\n\t\t\t}\n\t\t}\n\n\t\tthis.idRanges.append(localId, [localId, undefined]);\n\t\treturn localId;\n\t}\n\n\t/**\n\t * Registers a final ID with this normalizer.\n\t * If there are any local IDs at the tip of session-space that do not have a corresponding final, it will be registered (aligned) with\n\t * the first of those. Otherwise, will be registered as the next ID in session space in creation order. An example:\n\t *\n\t * Locals: [-1, -2, X, -4]\n\t * Finals: [ 0, 1, 2, X]\n\t * Calling `addFinalIds` with first === last === 5 results in the following:\n\t * Locals: [-1, -2, X, -4]\n\t * Finals: [ 0, 1, 2, 5]\n\t * Calling `addFinalIds` with first === last === 6 results in the following:\n\t * Locals: [-1, -2, X, -4, X]\n\t * Finals: [ 0, 1, 2, 5, 6]\n\t *\n\t * Non-contiguous final IDs (i.e. the first final after a \"gap\" in final space) must always correspond to a local ID. For example,\n\t * in the final call to `addFinalIds` above would fail if first === last === 9, because the resulting state would have a\n\t * non-contiguous final ID without a local form:\n\t * Locals: [-1, -2, X, -4, X]\n\t * Finals: [ 0, 1, 2, 5, 9]\n\t * ^final ID 9 is not contiguous and does not have a corresponding local ID\n\t */\n\tpublic addFinalIds(firstFinal: FinalCompressedId, lastFinal: FinalCompressedId, rangeObject: TRangeObject): void {\n\t\tassert(lastFinal >= firstFinal, 'Malformed normalization range.');\n\t\tconst [firstLocal, finalRangesObj] =\n\t\t\tthis.idRanges.last() ?? fail('Final IDs must be added to an existing local range.');\n\t\tconst [lastLocal, finalRanges] = finalRangesObj;\n\t\tlet nextLocal: LocalCompressedId;\n\t\tif (finalRanges === undefined) {\n\t\t\tfinalRangesObj[1] = [firstFinal, lastFinal, rangeObject];\n\t\t\tnextLocal = Math.min(this.nextLocalId, firstLocal - (lastFinal - firstFinal) - 1) as LocalCompressedId;\n\t\t} else {\n\t\t\tconst isSingle = isSingleRange(finalRanges);\n\t\t\tlet lastFinalRange: FinalRange<TRangeObject>;\n\t\t\tlet firstAlignedLocal: LocalCompressedId;\n\t\t\tif (isSingle) {\n\t\t\t\tfirstAlignedLocal = firstLocal;\n\t\t\t\tlastFinalRange = finalRanges;\n\t\t\t} else {\n\t\t\t\t[firstAlignedLocal, lastFinalRange] = finalRanges.last() ?? fail('Map should be non-empty.');\n\t\t\t}\n\n\t\t\tconst [firstAlignedFinal, lastAlignedFinal] = lastFinalRange;\n\t\t\tconst lastAlignedLocal = firstAlignedLocal - (lastAlignedFinal - firstAlignedFinal);\n\t\t\tnextLocal = Math.min(\n\t\t\t\tthis.nextLocalId,\n\t\t\t\tlastAlignedLocal - (lastFinal - firstFinal) - 2\n\t\t\t) as LocalCompressedId;\n\t\t\tif (firstFinal === lastAlignedFinal + 1) {\n\t\t\t\tlastFinalRange[1] = lastFinal;\n\t\t\t} else {\n\t\t\t\tconst alignedLocal = (lastAlignedLocal - 1) as LocalCompressedId;\n\t\t\t\tlet rangeMap: FinalRangesMap<TRangeObject>;\n\t\t\t\tif (isSingle) {\n\t\t\t\t\t// Convert the single range to a range collection\n\t\t\t\t\trangeMap = SessionIdNormalizer.makeFinalRangesMap();\n\t\t\t\t\trangeMap.append(firstAlignedLocal, lastFinalRange);\n\t\t\t\t\tfinalRangesObj[1] = rangeMap;\n\t\t\t\t} else {\n\t\t\t\t\trangeMap = finalRanges;\n\t\t\t\t}\n\t\t\t\trangeMap.append(alignedLocal, [firstFinal, lastFinal, rangeObject]);\n\t\t\t\tassert(alignedLocal >= lastLocal, 'Gaps in final space must align to a local.');\n\t\t\t}\n\t\t\tif (this.expensiveAsserts) {\n\t\t\t\tthis.idRanges.assertValid();\n\t\t\t}\n\t\t}\n\n\t\tthis.nextLocalId = nextLocal;\n\t}\n\n\t/**\n\t * Returns an enumerable of all session-space IDs known to this normalizer, in creation order.\n\t */\n\tpublic *[Symbol.iterator](): IterableIterator<SessionSpaceCompressedId> {\n\t\tfor (const [firstLocal, [lastLocal, finalRanges]] of this.idRanges.entries()) {\n\t\t\tfor (let i = firstLocal; i >= lastLocal; i--) {\n\t\t\t\tyield i;\n\t\t\t}\n\t\t\tif (finalRanges !== undefined) {\n\t\t\t\t// Safe to get only the last final range, as all others must have corresponding locals (see `addFinalIds` docs)\n\t\t\t\tlet lastFinalRange: FinalRange<TRangeObject>;\n\t\t\t\tlet alignedLocal: LocalCompressedId;\n\t\t\t\tif (isSingleRange(finalRanges)) {\n\t\t\t\t\talignedLocal = firstLocal;\n\t\t\t\t\tlastFinalRange = finalRanges;\n\t\t\t\t} else {\n\t\t\t\t\t[alignedLocal, lastFinalRange] = finalRanges.last() ?? fail('Map should be non-empty.');\n\t\t\t\t}\n\t\t\t\tconst [firstFinal, lastFinal] = lastFinalRange;\n\t\t\t\tconst localRangeDelta = alignedLocal - lastLocal;\n\t\t\t\tfor (let i = firstFinal + localRangeDelta + 1; i <= lastFinal; i++) {\n\t\t\t\t\tyield i as SessionSpaceCompressedId;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic serialize(): SerializedSessionIdNormalizer {\n\t\tconst serialized: Mutable<SerializedSessionIdNormalizer> = { localRanges: [] };\n\t\tconst localRanges = serialized.localRanges as Mutable<typeof serialized.localRanges>;\n\t\tfor (const [firstLocal, finalRanges] of this.idRanges.entries()) {\n\t\t\tconst [lastLocal, finalRangesTable] = finalRanges;\n\t\t\tif (finalRangesTable !== undefined) {\n\t\t\t\tconst serializedFinalRanges: [LocalCompressedId, FinalCompressedId, FinalCompressedId][] = [];\n\t\t\t\tfor (const [alignedLocal, [firstFinal, lastFinal]] of entries(firstLocal, finalRangesTable)) {\n\t\t\t\t\tserializedFinalRanges.push([alignedLocal, firstFinal, lastFinal]);\n\t\t\t\t}\n\t\t\t\tlocalRanges.push([firstLocal, lastLocal, serializedFinalRanges]);\n\t\t\t} else {\n\t\t\t\tlocalRanges.push([firstLocal, lastLocal]);\n\t\t\t}\n\t\t}\n\t\treturn serialized;\n\t}\n\n\tpublic static deserialize<TRangeObject>(\n\t\tserialized: SerializedSessionIdNormalizer,\n\t\tgetRangeObject: (finalId: FinalCompressedId) => TRangeObject\n\t): SessionIdNormalizer<TRangeObject> {\n\t\tconst normalizer = new SessionIdNormalizer<TRangeObject>();\n\t\tconst { idRanges } = normalizer;\n\t\tfor (const [firstLocal, lastLocal, serializedFinalRanges] of serialized.localRanges) {\n\t\t\tlet finalRanges: FinalRanges<TRangeObject> | undefined;\n\t\t\tif (serializedFinalRanges !== undefined) {\n\t\t\t\tassert(serializedFinalRanges.length !== 0, 'Empty range should not be reified.');\n\t\t\t\tif (serializedFinalRanges.length === 1) {\n\t\t\t\t\tconst [_, firstFinal, lastFinal] = serializedFinalRanges[0];\n\t\t\t\t\tfinalRanges = [firstFinal, lastFinal, getRangeObject(firstFinal)];\n\t\t\t\t} else {\n\t\t\t\t\tfinalRanges = SessionIdNormalizer.makeFinalRangesMap<TRangeObject>();\n\t\t\t\t\tfor (const [alignedLocal, firstFinal, lastFinal] of serializedFinalRanges) {\n\t\t\t\t\t\tfinalRanges.append(alignedLocal, [firstFinal, lastFinal, getRangeObject(firstFinal)]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tidRanges.append(firstLocal, [lastLocal, finalRanges]);\n\t\t}\n\t\treturn normalizer;\n\t}\n\n\tpublic equals(\n\t\tother: SessionIdNormalizer<TRangeObject>,\n\t\tcompareRangeObjects: (a: TRangeObject, b: TRangeObject) => boolean = (a, b) => a === b\n\t): boolean {\n\t\treturn this.idRanges.equals(other.idRanges, (localRangeA, localRangeB) => {\n\t\t\tconst [lastLocalA, finalRangesA] = localRangeA;\n\t\t\tconst [lastLocalB, finalRangesB] = localRangeB;\n\t\t\tif (finalRangesA === undefined || finalRangesB === undefined) {\n\t\t\t\treturn finalRangesA === finalRangesB;\n\t\t\t}\n\n\t\t\tconst rangeEquals = (finalRangeA: FinalRange<TRangeObject>, finalRangeB: FinalRange<TRangeObject>) => {\n\t\t\t\tconst [firstFinalA, lastFinalA, rangeObjectA] = finalRangeA;\n\t\t\t\tconst [firstFinalB, lastFinalB, rangeObjectB] = finalRangeB;\n\t\t\t\treturn (\n\t\t\t\t\tfirstFinalA === firstFinalB &&\n\t\t\t\t\tlastFinalA === lastFinalB &&\n\t\t\t\t\tcompareRangeObjects(rangeObjectA, rangeObjectB)\n\t\t\t\t);\n\t\t\t};\n\n\t\t\tif (isSingleRange(finalRangesA) || isSingleRange(finalRangesB)) {\n\t\t\t\tif (!isSingleRange(finalRangesA) || !isSingleRange(finalRangesB)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn rangeEquals(finalRangesA, finalRangesB);\n\t\t\t}\n\n\t\t\treturn lastLocalA === lastLocalB && finalRangesA.equals(finalRangesB, rangeEquals);\n\t\t});\n\t}\n}\n\n/**\n * Serialized table for normalizing IDs made by the local session.\n *\n * TODO: Move this into ID compressor persisted types when integrated.\n */\nexport interface SerializedSessionIdNormalizer {\n\treadonly localRanges: readonly (readonly [\n\t\tfirstLocal: LocalCompressedId,\n\t\tlastLocal: LocalCompressedId,\n\t\tfinalRanges?: readonly (readonly [\n\t\t\talignedLocal: LocalCompressedId,\n\t\t\tfirstFinal: FinalCompressedId,\n\t\t\tlastFinal: FinalCompressedId\n\t\t])[]\n\t])[];\n}\n\ntype FinalRange<TRangeObject> = [\n\tfirstFinal: FinalCompressedId,\n\tlastFinal: FinalCompressedId,\n\trangeObject: TRangeObject\n];\n\ntype FinalRangesMap<TRangeObject> = AppendOnlyDoublySortedMap<\n\tLocalCompressedId,\n\tFinalRange<TRangeObject>,\n\tFinalCompressedId\n>;\n\ntype FinalRanges<TRangeObject> = FinalRange<TRangeObject> | FinalRangesMap<TRangeObject>;\n\nfunction isSingleRange<TRangeObject>(ranges: FinalRanges<TRangeObject>): ranges is FinalRange<TRangeObject> {\n\treturn Array.isArray(ranges);\n}\n\nfunction getLastRange<TRangeObject>(finalRanges: FinalRanges<TRangeObject>): FinalRange<TRangeObject> {\n\tif (isSingleRange(finalRanges)) {\n\t\treturn finalRanges;\n\t}\n\treturn (finalRanges.last() ?? fail('Map must be non-empty'))[1];\n}\n\nfunction getFirstRange<TRangeObject>(finalRanges: FinalRanges<TRangeObject>): FinalRange<TRangeObject> {\n\tif (isSingleRange(finalRanges)) {\n\t\treturn finalRanges;\n\t}\n\treturn (finalRanges.first() ?? fail('Map must be non-empty'))[1];\n}\n\nfunction extractFirstFinalFromRange<TRangeObject>(finalRange: FinalRange<TRangeObject>): FinalCompressedId {\n\treturn finalRange[0];\n}\n\nfunction getPairOrNextLowerByValue<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined,\n\tfinalId: FinalCompressedId\n): readonly [LocalCompressedId, FinalRange<TRangeObject>] | undefined {\n\tif (finalRanges === undefined) {\n\t\treturn undefined;\n\t}\n\tif (isSingleRange(finalRanges)) {\n\t\tif (finalId < finalRanges[0]) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [firstLocal, finalRanges];\n\t}\n\treturn finalRanges.getPairOrNextLowerByValue(finalId);\n}\n\nfunction getPairOrNextLower<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined,\n\tlocalId: LocalCompressedId\n): readonly [LocalCompressedId, FinalRange<TRangeObject>] | undefined {\n\tif (finalRanges === undefined) {\n\t\treturn undefined;\n\t}\n\tif (isSingleRange(finalRanges)) {\n\t\tif (localId > firstLocal) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [firstLocal, finalRanges];\n\t}\n\treturn finalRanges.getPairOrNextLower(localId);\n}\n\nfunction* entries<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined\n): IterableIterator<readonly [LocalCompressedId, FinalRange<TRangeObject>]> {\n\tif (finalRanges !== undefined) {\n\t\tif (isSingleRange(finalRanges)) {\n\t\t\tyield [firstLocal, finalRanges];\n\t\t} else {\n\t\t\tfor (const range of finalRanges.entries()) {\n\t\t\t\tyield range;\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SessionIdNormalizer.js","sourceRoot":"","sources":["../../src/id-compressor/SessionIdNormalizer.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable @typescript-eslint/restrict-plus-operands */\n\nimport { assert, compareFiniteNumbers, compareFiniteNumbersReversed, fail, Mutable } from '../Common';\nimport { FinalCompressedId, LocalCompressedId, SessionSpaceCompressedId } from '../Identifiers';\nimport { AppendOnlyDoublySortedMap } from './AppendOnlySortedMap';\nimport { SerializedSessionIdNormalizer } from './persisted-types';\n\n/**\n * Maps IDs created by a session between their local and final forms (i.e. normalization). These IDs are in a contiguous range.\n * The local and final forms of IDs made by a session can be thought of as two equal-length sparse arrays, aligned such\n * that normalizeLocalToFinal(locals[i]) === finals[i] and vice versa.\n * Below is an example to illustrate how various mappings can arise:\n *\n * +- Creation Index\n * / +- Locals\n * / / +- Finals\n * / / /\n * ---+-----+----\n * 0 | -1 | 0 -|___ Two IDs are allocated as locals since no cluster exists. A new cluster is created when acked.\n * 1 | -2 | 1 -|\n * 2 | | 2 -|\n * 3 | | 3 --|-- Three more IDs are allocated as finals eagerly since a cluster exists with available capacity.\n * 4 | | 4 -|\n * 5 | -6 | 10 ----- One ID is allocated as a local (it overflows the existing cluster) and a new cluster is created after ack.\n * 6 | | 11 ----- One ID is allocated as a final eagerly into the existing cluster.\n * 7 | -8 | 12 ----- A local ID with an override is allocated. The override forces it to be a local ID.\n * 8 | | 13\n * 9 | | 14\n * 10 | -11 | ----- A local ID is allocated. It has no corresponding final ID since it has not been acked.\n *\n * Note that in this example, some IDs (those at indices 2, 3, 4, 6, 8, and 9) have no local form. The ID at index 10 has no final form.\n * These kinds of \"gaps\" occur due to the timing of allocation calls on the client and how they relate to finalization/cluster creation,\n * which depends on receiving an ack/sequence number from the server. Given this context, \"session space\" can be thought of as:\n *\n * \t\tfor each index in the range of IDs created by a session:\n * \t\t\tthe local form if it exists, otherwise the final form\n *\n * This class is designed to efficiently build and query these mappings by leveraging the facts that much of the range (in both local and\n * final space) is uninterrupted by \"gaps\" and can be compactly represented by a (first, last) pair and is easily binary searched for\n * normalization between local and final space.\n */\nexport class SessionIdNormalizer<TRangeObject> {\n\tprivate nextLocalId: LocalCompressedId = -1 as LocalCompressedId;\n\tprivate readonly idRanges: AppendOnlyDoublySortedMap<\n\t\tLocalCompressedId,\n\t\t[lastLocal: LocalCompressedId, finalRanges: FinalRanges<TRangeObject> | undefined],\n\t\tFinalCompressedId\n\t> = new AppendOnlyDoublySortedMap(\n\t\tcompareFiniteNumbersReversed,\n\t\t([_, finalRanges]) => {\n\t\t\tif (finalRanges !== undefined) {\n\t\t\t\tconst first = getFirstRange(finalRanges);\n\t\t\t\treturn extractFirstFinalFromRange(first);\n\t\t\t}\n\t\t\treturn Number.POSITIVE_INFINITY as FinalCompressedId;\n\t\t},\n\t\tcompareFiniteNumbers\n\t);\n\n\tpublic constructor(private readonly expensiveAsserts = false) {}\n\n\t/**\n\t * Converts the final ID to its session-space representation.\n\t * This will be the corresponding local if a local form exists, and `finalId` otherwise.\n\t */\n\tpublic getSessionSpaceId(finalId: FinalCompressedId): SessionSpaceCompressedId | undefined {\n\t\tconst localRange = this.idRanges.getPairOrNextLowerByValue(finalId);\n\t\tif (localRange !== undefined) {\n\t\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\t\tconst finalRange = getPairOrNextLowerByValue(firstLocal, finalRanges, finalId);\n\t\t\tif (finalRange !== undefined) {\n\t\t\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\t\t\tif (finalId <= lastFinal) {\n\t\t\t\t\tconst localRangeDelta = alignedLocal - lastLocal;\n\t\t\t\t\tconst finalDelta = finalId - firstFinal;\n\t\t\t\t\tif (finalDelta <= localRangeDelta) {\n\t\t\t\t\t\treturn (alignedLocal - finalDelta) as LocalCompressedId;\n\t\t\t\t\t}\n\t\t\t\t\t// `finalId` was an eagerly generated final ID\n\t\t\t\t\treturn finalId as SessionSpaceCompressedId;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Converts the local ID to its corresponding final ID, if one exists.\n\t */\n\tpublic getFinalId(localId: LocalCompressedId): [FinalCompressedId, TRangeObject] | undefined {\n\t\tconst localRange =\n\t\t\tthis.idRanges.getPairOrNextLower(localId) ?? fail('Local ID was never recorded with this normalizer.');\n\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\tif (localId < lastLocal) {\n\t\t\tfail('Local ID was never recorded with this normalizer.');\n\t\t}\n\t\tconst finalRange = getPairOrNextLower(firstLocal, finalRanges, localId);\n\t\tif (finalRange !== undefined) {\n\t\t\tconst [alignedLocal, [firstFinal, lastFinal, rangeObject]] = finalRange;\n\t\t\tconst rangeDelta = lastFinal - firstFinal;\n\t\t\tconst localDelta = alignedLocal - localId;\n\t\t\tif (localDelta <= rangeDelta) {\n\t\t\t\t// Local is within a range segment that has a corresponding final\n\t\t\t\treturn [(firstFinal + localDelta) as FinalCompressedId, rangeObject];\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Returns the index of the supplied session-space ID in the total range of IDs created by the session, if the ID was created\n\t * by the session for this `SessionIdNormalizer`.\n\t */\n\tpublic getCreationIndex(finalId: FinalCompressedId): number | undefined {\n\t\tconst localRange = this.idRanges.getPairOrNextLowerByValue(finalId);\n\t\tif (localRange !== undefined) {\n\t\t\tconst [firstLocal, [_, finalRanges]] = localRange;\n\t\t\tconst finalRange = getPairOrNextLowerByValue(firstLocal, finalRanges, finalId);\n\t\t\tif (finalRange !== undefined) {\n\t\t\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\t\t\tif (finalId <= lastFinal) {\n\t\t\t\t\tconst finalDelta = finalId - firstFinal;\n\t\t\t\t\treturn -alignedLocal - 1 + finalDelta;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Returns the session-space ID at the supplied creation index, if one exists.\n\t */\n\tpublic getIdByCreationIndex(index: number): SessionSpaceCompressedId | undefined {\n\t\tconst localByIndex = -(index + 1) as LocalCompressedId;\n\t\tconst localRange = this.idRanges.getPairOrNextLower(localByIndex);\n\t\tif (localRange === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst [firstLocal, [lastLocal, finalRanges]] = localRange;\n\t\tif (localByIndex >= lastLocal) {\n\t\t\treturn localByIndex;\n\t\t}\n\t\tconst finalRange =\n\t\t\tgetPairOrNextLower(firstLocal, finalRanges, localByIndex) ??\n\t\t\tfail('Final ranges not aligned with owning local range.');\n\n\t\tconst [alignedLocal, [firstFinal, lastFinal]] = finalRange;\n\t\tconst localDelta = alignedLocal - localByIndex;\n\t\tconst finalId = firstFinal + localDelta;\n\t\tif (finalId <= lastFinal) {\n\t\t\t// `finalId` was an eagerly generated final ID\n\t\t\treturn finalId as SessionSpaceCompressedId;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate static makeFinalRangesMap<TRangeObject>(): FinalRangesMap<TRangeObject> {\n\t\treturn new AppendOnlyDoublySortedMap(\n\t\t\tcompareFiniteNumbersReversed,\n\t\t\textractFirstFinalFromRange,\n\t\t\tcompareFiniteNumbers\n\t\t);\n\t}\n\n\t/**\n\t * Returns the last final ID known to this normalizer.\n\t */\n\tpublic getLastFinalId(): FinalCompressedId | undefined {\n\t\tconst lastIndex = this.idRanges.size - 1;\n\t\tconst secondToLast = Math.max(0, lastIndex - 1);\n\t\tfor (let i = lastIndex; i >= secondToLast; i--) {\n\t\t\tconst localRange = this.idRanges.getAtIndex(i);\n\t\t\tif (localRange !== undefined) {\n\t\t\t\tconst finalRanges = localRange[1][1];\n\t\t\t\tif (finalRanges !== undefined) {\n\t\t\t\t\treturn getLastRange(finalRanges)[1];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Registers and returns the next ID in local space with this normalizer. An example:\n\t *\n\t * Locals: [-1, -2, X, X]\n\t * Finals: [ 0, 1, 2, 3]\n\t * In this scenario, a call to this method would generate and return -5.\n\t */\n\tpublic addLocalId(): LocalCompressedId {\n\t\tconst localId = this.nextLocalId-- as LocalCompressedId;\n\t\tconst lastLocalRange = this.idRanges.last();\n\t\tif (lastLocalRange !== undefined) {\n\t\t\tconst lastLocal = lastLocalRange[1][0];\n\t\t\tif (localId === lastLocal - 1) {\n\t\t\t\t// New local simply expands the last local range tracked\n\t\t\t\tlastLocalRange[1][0] = localId;\n\t\t\t\treturn localId;\n\t\t\t}\n\t\t}\n\n\t\tif (this.expensiveAsserts) {\n\t\t\tif (lastLocalRange === undefined) {\n\t\t\t\tassert(localId === -1, 'Local ID space must start at -1.');\n\t\t\t} else {\n\t\t\t\tconst [firstLocal, [_, finalRanges]] = lastLocalRange;\n\t\t\t\tlet finalDelta = 0;\n\t\t\t\tfor (const [_, [firstFinal, lastFinal]] of entries(firstLocal, finalRanges)) {\n\t\t\t\t\tfinalDelta += lastFinal - firstFinal + 1;\n\t\t\t\t}\n\t\t\t\tassert(localId === firstLocal - finalDelta, 'Local ID space must be contiguous.');\n\t\t\t}\n\t\t}\n\n\t\tthis.idRanges.append(localId, [localId, undefined]);\n\t\treturn localId;\n\t}\n\n\t/**\n\t * Registers a final ID with this normalizer.\n\t * If there are any local IDs at the tip of session-space that do not have a corresponding final, it will be registered (aligned) with\n\t * the first of those. Otherwise, will be registered as the next ID in session space in creation order. An example:\n\t *\n\t * Locals: [-1, -2, X, -4]\n\t * Finals: [ 0, 1, 2, X]\n\t * Calling `addFinalIds` with first === last === 5 results in the following:\n\t * Locals: [-1, -2, X, -4]\n\t * Finals: [ 0, 1, 2, 5]\n\t * Calling `addFinalIds` with first === last === 6 results in the following:\n\t * Locals: [-1, -2, X, -4, X]\n\t * Finals: [ 0, 1, 2, 5, 6]\n\t *\n\t * Non-contiguous final IDs (i.e. the first final after a \"gap\" in final space) must always correspond to a local ID. For example,\n\t * in the final call to `addFinalIds` above would fail if first === last === 9, because the resulting state would have a\n\t * non-contiguous final ID without a local form:\n\t * Locals: [-1, -2, X, -4, X]\n\t * Finals: [ 0, 1, 2, 5, 9]\n\t * ^final ID 9 is not contiguous and does not have a corresponding local ID\n\t */\n\tpublic addFinalIds(firstFinal: FinalCompressedId, lastFinal: FinalCompressedId, rangeObject: TRangeObject): void {\n\t\tassert(lastFinal >= firstFinal, 'Malformed normalization range.');\n\t\tconst [firstLocal, finalRangesObj] =\n\t\t\tthis.idRanges.last() ?? fail('Final IDs must be added to an existing local range.');\n\t\tconst [lastLocal, finalRanges] = finalRangesObj;\n\t\tlet nextLocal: LocalCompressedId;\n\t\tif (finalRanges === undefined) {\n\t\t\tfinalRangesObj[1] = [firstFinal, lastFinal, rangeObject];\n\t\t\tnextLocal = Math.min(this.nextLocalId, firstLocal - (lastFinal - firstFinal) - 1) as LocalCompressedId;\n\t\t} else {\n\t\t\tconst isSingle = isSingleRange(finalRanges);\n\t\t\tlet lastFinalRange: FinalRange<TRangeObject>;\n\t\t\tlet firstAlignedLocal: LocalCompressedId;\n\t\t\tif (isSingle) {\n\t\t\t\tfirstAlignedLocal = firstLocal;\n\t\t\t\tlastFinalRange = finalRanges;\n\t\t\t} else {\n\t\t\t\t[firstAlignedLocal, lastFinalRange] = finalRanges.last() ?? fail('Map should be non-empty.');\n\t\t\t}\n\n\t\t\tconst [firstAlignedFinal, lastAlignedFinal] = lastFinalRange;\n\t\t\tconst lastAlignedLocal = firstAlignedLocal - (lastAlignedFinal - firstAlignedFinal);\n\t\t\tnextLocal = Math.min(\n\t\t\t\tthis.nextLocalId,\n\t\t\t\tlastAlignedLocal - (lastFinal - firstFinal) - 2\n\t\t\t) as LocalCompressedId;\n\t\t\tif (firstFinal === lastAlignedFinal + 1) {\n\t\t\t\tlastFinalRange[1] = lastFinal;\n\t\t\t} else {\n\t\t\t\tconst alignedLocal = (lastAlignedLocal - 1) as LocalCompressedId;\n\t\t\t\tlet rangeMap: FinalRangesMap<TRangeObject>;\n\t\t\t\tif (isSingle) {\n\t\t\t\t\t// Convert the single range to a range collection\n\t\t\t\t\trangeMap = SessionIdNormalizer.makeFinalRangesMap();\n\t\t\t\t\trangeMap.append(firstAlignedLocal, lastFinalRange);\n\t\t\t\t\tfinalRangesObj[1] = rangeMap;\n\t\t\t\t} else {\n\t\t\t\t\trangeMap = finalRanges;\n\t\t\t\t}\n\t\t\t\trangeMap.append(alignedLocal, [firstFinal, lastFinal, rangeObject]);\n\t\t\t\tassert(alignedLocal >= lastLocal, 'Gaps in final space must align to a local.');\n\t\t\t}\n\t\t\tif (this.expensiveAsserts) {\n\t\t\t\tthis.idRanges.assertValid();\n\t\t\t}\n\t\t}\n\n\t\tthis.nextLocalId = nextLocal;\n\t}\n\n\t/**\n\t * Returns an enumerable of all session-space IDs known to this normalizer, in creation order.\n\t */\n\tpublic *[Symbol.iterator](): IterableIterator<SessionSpaceCompressedId> {\n\t\tfor (const [firstLocal, [lastLocal, finalRanges]] of this.idRanges.entries()) {\n\t\t\tfor (let i = firstLocal; i >= lastLocal; i--) {\n\t\t\t\tyield i;\n\t\t\t}\n\t\t\tif (finalRanges !== undefined) {\n\t\t\t\t// Safe to get only the last final range, as all others must have corresponding locals (see `addFinalIds` docs)\n\t\t\t\tlet lastFinalRange: FinalRange<TRangeObject>;\n\t\t\t\tlet alignedLocal: LocalCompressedId;\n\t\t\t\tif (isSingleRange(finalRanges)) {\n\t\t\t\t\talignedLocal = firstLocal;\n\t\t\t\t\tlastFinalRange = finalRanges;\n\t\t\t\t} else {\n\t\t\t\t\t[alignedLocal, lastFinalRange] = finalRanges.last() ?? fail('Map should be non-empty.');\n\t\t\t\t}\n\t\t\t\tconst [firstFinal, lastFinal] = lastFinalRange;\n\t\t\t\tconst localRangeDelta = alignedLocal - lastLocal;\n\t\t\t\tfor (let i = firstFinal + localRangeDelta + 1; i <= lastFinal; i++) {\n\t\t\t\t\tyield i as SessionSpaceCompressedId;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic serialize(): SerializedSessionIdNormalizer {\n\t\tconst serialized: Mutable<SerializedSessionIdNormalizer> = { localRanges: [], nextLocalId: this.nextLocalId };\n\t\tconst localRanges = serialized.localRanges as Mutable<typeof serialized.localRanges>;\n\t\tfor (const [firstLocal, finalRanges] of this.idRanges.entries()) {\n\t\t\tconst [lastLocal, finalRangesTable] = finalRanges;\n\t\t\tif (finalRangesTable !== undefined) {\n\t\t\t\tconst serializedFinalRanges: [LocalCompressedId, FinalCompressedId, FinalCompressedId][] = [];\n\t\t\t\tfor (const [alignedLocal, [firstFinal, lastFinal]] of entries(firstLocal, finalRangesTable)) {\n\t\t\t\t\tserializedFinalRanges.push([alignedLocal, firstFinal, lastFinal]);\n\t\t\t\t}\n\t\t\t\tlocalRanges.push([firstLocal, lastLocal, serializedFinalRanges]);\n\t\t\t} else {\n\t\t\t\tlocalRanges.push([firstLocal, lastLocal]);\n\t\t\t}\n\t\t}\n\t\treturn serialized;\n\t}\n\n\tpublic static deserialize<TRangeObject>(\n\t\tserialized: SerializedSessionIdNormalizer,\n\t\tgetRangeObject: (finalId: FinalCompressedId) => TRangeObject\n\t): SessionIdNormalizer<TRangeObject> {\n\t\tconst normalizer = new SessionIdNormalizer<TRangeObject>();\n\t\tconst { idRanges } = normalizer;\n\t\tfor (const [firstLocal, lastLocal, serializedFinalRanges] of serialized.localRanges) {\n\t\t\tlet finalRanges: FinalRanges<TRangeObject> | undefined;\n\t\t\tif (serializedFinalRanges !== undefined) {\n\t\t\t\tassert(serializedFinalRanges.length !== 0, 'Empty range should not be reified.');\n\t\t\t\tif (serializedFinalRanges.length === 1) {\n\t\t\t\t\tconst [_, firstFinal, lastFinal] = serializedFinalRanges[0];\n\t\t\t\t\tfinalRanges = [firstFinal, lastFinal, getRangeObject(firstFinal)];\n\t\t\t\t} else {\n\t\t\t\t\tfinalRanges = SessionIdNormalizer.makeFinalRangesMap<TRangeObject>();\n\t\t\t\t\tfor (const [alignedLocal, firstFinal, lastFinal] of serializedFinalRanges) {\n\t\t\t\t\t\tfinalRanges.append(alignedLocal, [firstFinal, lastFinal, getRangeObject(firstFinal)]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tidRanges.append(firstLocal, [lastLocal, finalRanges]);\n\t\t}\n\t\tnormalizer.nextLocalId = serialized.nextLocalId;\n\t\treturn normalizer;\n\t}\n\n\tpublic equals(\n\t\tother: SessionIdNormalizer<TRangeObject>,\n\t\tcompareRangeObjects: (a: TRangeObject, b: TRangeObject) => boolean = (a, b) => a === b\n\t): boolean {\n\t\treturn (\n\t\t\tthis.nextLocalId === other.nextLocalId &&\n\t\t\tthis.idRanges.equals(other.idRanges, (localRangeA, localRangeB) => {\n\t\t\t\tconst [lastLocalA, finalRangesA] = localRangeA;\n\t\t\t\tconst [lastLocalB, finalRangesB] = localRangeB;\n\t\t\t\tif (finalRangesA === undefined || finalRangesB === undefined) {\n\t\t\t\t\treturn finalRangesA === finalRangesB;\n\t\t\t\t}\n\n\t\t\t\tconst rangeEquals = (finalRangeA: FinalRange<TRangeObject>, finalRangeB: FinalRange<TRangeObject>) => {\n\t\t\t\t\tconst [firstFinalA, lastFinalA, rangeObjectA] = finalRangeA;\n\t\t\t\t\tconst [firstFinalB, lastFinalB, rangeObjectB] = finalRangeB;\n\t\t\t\t\treturn (\n\t\t\t\t\t\tfirstFinalA === firstFinalB &&\n\t\t\t\t\t\tlastFinalA === lastFinalB &&\n\t\t\t\t\t\tcompareRangeObjects(rangeObjectA, rangeObjectB)\n\t\t\t\t\t);\n\t\t\t\t};\n\n\t\t\t\tif (isSingleRange(finalRangesA) || isSingleRange(finalRangesB)) {\n\t\t\t\t\tif (!isSingleRange(finalRangesA) || !isSingleRange(finalRangesB)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn rangeEquals(finalRangesA, finalRangesB);\n\t\t\t\t}\n\n\t\t\t\treturn lastLocalA === lastLocalB && finalRangesA.equals(finalRangesB, rangeEquals);\n\t\t\t})\n\t\t);\n\t}\n}\n\ntype FinalRange<TRangeObject> = [\n\tfirstFinal: FinalCompressedId,\n\tlastFinal: FinalCompressedId,\n\trangeObject: TRangeObject\n];\n\ntype FinalRangesMap<TRangeObject> = AppendOnlyDoublySortedMap<\n\tLocalCompressedId,\n\tFinalRange<TRangeObject>,\n\tFinalCompressedId\n>;\n\ntype FinalRanges<TRangeObject> = FinalRange<TRangeObject> | FinalRangesMap<TRangeObject>;\n\nfunction isSingleRange<TRangeObject>(ranges: FinalRanges<TRangeObject>): ranges is FinalRange<TRangeObject> {\n\treturn Array.isArray(ranges);\n}\n\nfunction getLastRange<TRangeObject>(finalRanges: FinalRanges<TRangeObject>): FinalRange<TRangeObject> {\n\tif (isSingleRange(finalRanges)) {\n\t\treturn finalRanges;\n\t}\n\treturn (finalRanges.last() ?? fail('Map must be non-empty'))[1];\n}\n\nfunction getFirstRange<TRangeObject>(finalRanges: FinalRanges<TRangeObject>): FinalRange<TRangeObject> {\n\tif (isSingleRange(finalRanges)) {\n\t\treturn finalRanges;\n\t}\n\treturn (finalRanges.first() ?? fail('Map must be non-empty'))[1];\n}\n\nfunction extractFirstFinalFromRange<TRangeObject>(finalRange: FinalRange<TRangeObject>): FinalCompressedId {\n\treturn finalRange[0];\n}\n\nfunction getPairOrNextLowerByValue<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined,\n\tfinalId: FinalCompressedId\n): readonly [LocalCompressedId, FinalRange<TRangeObject>] | undefined {\n\tif (finalRanges === undefined) {\n\t\treturn undefined;\n\t}\n\tif (isSingleRange(finalRanges)) {\n\t\tif (finalId < finalRanges[0]) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [firstLocal, finalRanges];\n\t}\n\treturn finalRanges.getPairOrNextLowerByValue(finalId);\n}\n\nfunction getPairOrNextLower<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined,\n\tlocalId: LocalCompressedId\n): readonly [LocalCompressedId, FinalRange<TRangeObject>] | undefined {\n\tif (finalRanges === undefined) {\n\t\treturn undefined;\n\t}\n\tif (isSingleRange(finalRanges)) {\n\t\tif (localId > firstLocal) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn [firstLocal, finalRanges];\n\t}\n\treturn finalRanges.getPairOrNextLower(localId);\n}\n\nfunction* entries<TRangeObject>(\n\tfirstLocal: LocalCompressedId,\n\tfinalRanges: FinalRanges<TRangeObject> | undefined\n): IterableIterator<readonly [LocalCompressedId, FinalRange<TRangeObject>]> {\n\tif (finalRanges !== undefined) {\n\t\tif (isSingleRange(finalRanges)) {\n\t\t\tyield [firstLocal, finalRanges];\n\t\t} else {\n\t\t\tfor (const range of finalRanges.entries()) {\n\t\t\t\tyield range;\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
@@ -48,20 +48,39 @@ export declare type SerializedCluster = readonly [
|
|
|
48
48
|
*/
|
|
49
49
|
overrides?: SerializedClusterOverrides
|
|
50
50
|
];
|
|
51
|
-
export declare type SerializedLocalOverrides = readonly [LocalCompressedId, string][];
|
|
51
|
+
export declare type SerializedLocalOverrides = readonly (readonly [LocalCompressedId, string])[];
|
|
52
52
|
export interface SerializedLocalState {
|
|
53
53
|
/**
|
|
54
54
|
* The total number of local IDs created by this session
|
|
55
55
|
*/
|
|
56
|
-
localIdCount: number;
|
|
56
|
+
readonly localIdCount: number;
|
|
57
57
|
/**
|
|
58
58
|
* Overrides generated by this session. Omitted if no local overrides exist in the session.
|
|
59
59
|
*/
|
|
60
|
-
overrides?: SerializedLocalOverrides;
|
|
60
|
+
readonly overrides?: SerializedLocalOverrides;
|
|
61
61
|
/**
|
|
62
62
|
* The most recent local ID in a range returned by `takeNextCreationRange`.
|
|
63
63
|
*/
|
|
64
|
-
lastTakenLocalId: LocalCompressedId | undefined;
|
|
64
|
+
readonly lastTakenLocalId: LocalCompressedId | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Serialized table for normalizing IDs made by the local session.
|
|
67
|
+
*/
|
|
68
|
+
readonly sessionNormalizer: SerializedSessionIdNormalizer;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Serialized table for normalizing IDs made by the local session.
|
|
72
|
+
*/
|
|
73
|
+
export interface SerializedSessionIdNormalizer {
|
|
74
|
+
readonly nextLocalId: LocalCompressedId;
|
|
75
|
+
readonly localRanges: readonly (readonly [
|
|
76
|
+
firstLocal: LocalCompressedId,
|
|
77
|
+
lastLocal: LocalCompressedId,
|
|
78
|
+
finalRanges?: readonly (readonly [
|
|
79
|
+
alignedLocal: LocalCompressedId,
|
|
80
|
+
firstFinal: FinalCompressedId,
|
|
81
|
+
lastFinal: FinalCompressedId
|
|
82
|
+
])[]
|
|
83
|
+
])[];
|
|
65
84
|
}
|
|
66
85
|
/**
|
|
67
86
|
* The minimal required contents of a serialized IdCompressor.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"0.0.1.d.ts","sourceRoot":"","sources":["../../../src/id-compressor/persisted-types/0.0.1.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,MAAM,mBAAmB,CAAC;AAE3B;;GAEG;AACH,oBAAY,qBAAqB,GAAG,SAAS;IAC5C;;OAEG;IACH,SAAS,EAAE,SAAS;IAEpB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM;CACtB,CAAC;AAEF,oBAAY,0BAA0B,GAAG,SAAS;IACjD,mFAAmF;IACnF,oBAAoB,EAAE,MAAM;IAC5B,0BAA0B;IAC1B,QAAQ,EAAE,MAAM;IAChB,+HAA+H;IAC/H,YAAY,CAAC,EAAE,iBAAiB;CAChC,EAAE,CAAC;AAEJ;;GAEG;AACH,oBAAY,iBAAiB,GAAG,SAAS;IACxC;;;OAGG;IACH,YAAY,EAAE,MAAM;IAEpB;;OAEG;IACH,QAAQ,EAAE,MAAM;IAEhB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,0BAA0B;IAEtD;;OAEG;IACH,SAAS,CAAC,EAAE,0BAA0B;CACtC,CAAC;AAEF,oBAAY,wBAAwB,GAAG,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"0.0.1.d.ts","sourceRoot":"","sources":["../../../src/id-compressor/persisted-types/0.0.1.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"0.0.1.js","sourceRoot":"","sources":["../../../src/id-compressor/persisted-types/0.0.1.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tAttributionId,\n\tFinalCompressedId,\n\tLocalCompressedId,\n\tOpSpaceCompressedId,\n\tSessionId,\n} from '../../Identifiers';\n\n/**\n * A serialized ID allocation session for an `IdCompressor`.\n */\nexport type SerializedSessionData = readonly [\n\t/**\n\t * The ID of the session.\n\t */\n\tsessionId: SessionId,\n\n\t/**\n\t * Index into the serialized AttributionIDs array; points to the attribution ID provided for this session\n\t */\n\tattributionId?: number\n];\n\nexport type SerializedClusterOverrides = readonly [\n\t/** The overridden final ID, represented as an index into the cluster's ID range */\n\toverriddenFinalIndex: number, // A cluster with base UUID '...beef' and an `overriddenFinalIndex` of 3 would correspond to '...bef2'\n\t/** The override string */\n\toverride: string,\n\t/** The first ID that was finalized and associated with this override, set only if different than the `overriddenFinalIndex` */\n\toverriddenId?: FinalCompressedId\n][];\n\n/**\n * A serialized final ID cluster.\n */\nexport type SerializedCluster = readonly [\n\t/**\n\t * Index into the serialized sessions array. Can be converted into a baseUuid via its order in `clusters`.\n\t * If negative, then this cluster was created by the local session.\n\t */\n\tsessionIndex: number,\n\n\t/**\n\t * The capacity of the cluster.\n\t */\n\tcapacity: number,\n\n\t/**\n\t * The number of IDs in the cluster. Omitted if count === capacity.\n\t * --OR--\n\t * The overrides in this cluster. Omitted if no overrides exist in the cluster.\n\t */\n\tcountOrOverrides?: number | SerializedClusterOverrides,\n\n\t/**\n\t * Overrides in this cluster. Omitted if no overrides exist in the cluster.\n\t */\n\toverrides?: SerializedClusterOverrides\n];\n\nexport type SerializedLocalOverrides = readonly [LocalCompressedId, string][];\n\nexport interface SerializedLocalState {\n\t/**\n\t * The total number of local IDs created by this session\n\t */\n\
|
|
1
|
+
{"version":3,"file":"0.0.1.js","sourceRoot":"","sources":["../../../src/id-compressor/persisted-types/0.0.1.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tAttributionId,\n\tFinalCompressedId,\n\tLocalCompressedId,\n\tOpSpaceCompressedId,\n\tSessionId,\n} from '../../Identifiers';\n\n/**\n * A serialized ID allocation session for an `IdCompressor`.\n */\nexport type SerializedSessionData = readonly [\n\t/**\n\t * The ID of the session.\n\t */\n\tsessionId: SessionId,\n\n\t/**\n\t * Index into the serialized AttributionIDs array; points to the attribution ID provided for this session\n\t */\n\tattributionId?: number\n];\n\nexport type SerializedClusterOverrides = readonly [\n\t/** The overridden final ID, represented as an index into the cluster's ID range */\n\toverriddenFinalIndex: number, // A cluster with base UUID '...beef' and an `overriddenFinalIndex` of 3 would correspond to '...bef2'\n\t/** The override string */\n\toverride: string,\n\t/** The first ID that was finalized and associated with this override, set only if different than the `overriddenFinalIndex` */\n\toverriddenId?: FinalCompressedId\n][];\n\n/**\n * A serialized final ID cluster.\n */\nexport type SerializedCluster = readonly [\n\t/**\n\t * Index into the serialized sessions array. Can be converted into a baseUuid via its order in `clusters`.\n\t * If negative, then this cluster was created by the local session.\n\t */\n\tsessionIndex: number,\n\n\t/**\n\t * The capacity of the cluster.\n\t */\n\tcapacity: number,\n\n\t/**\n\t * The number of IDs in the cluster. Omitted if count === capacity.\n\t * --OR--\n\t * The overrides in this cluster. Omitted if no overrides exist in the cluster.\n\t */\n\tcountOrOverrides?: number | SerializedClusterOverrides,\n\n\t/**\n\t * Overrides in this cluster. Omitted if no overrides exist in the cluster.\n\t */\n\toverrides?: SerializedClusterOverrides\n];\n\nexport type SerializedLocalOverrides = readonly (readonly [LocalCompressedId, string])[];\n\nexport interface SerializedLocalState {\n\t/**\n\t * The total number of local IDs created by this session\n\t */\n\treadonly localIdCount: number;\n\t/**\n\t * Overrides generated by this session. Omitted if no local overrides exist in the session.\n\t */\n\treadonly overrides?: SerializedLocalOverrides;\n\n\t/**\n\t * The most recent local ID in a range returned by `takeNextCreationRange`.\n\t */\n\treadonly lastTakenLocalId: LocalCompressedId | undefined;\n\n\t/**\n\t * Serialized table for normalizing IDs made by the local session.\n\t */\n\treadonly sessionNormalizer: SerializedSessionIdNormalizer;\n}\n\n/**\n * Serialized table for normalizing IDs made by the local session.\n */\nexport interface SerializedSessionIdNormalizer {\n\treadonly nextLocalId: LocalCompressedId;\n\treadonly localRanges: readonly (readonly [\n\t\tfirstLocal: LocalCompressedId,\n\t\tlastLocal: LocalCompressedId,\n\t\tfinalRanges?: readonly (readonly [\n\t\t\talignedLocal: LocalCompressedId,\n\t\t\tfirstFinal: FinalCompressedId,\n\t\t\tlastFinal: FinalCompressedId\n\t\t])[]\n\t])[];\n}\n\n/**\n * The minimal required contents of a serialized IdCompressor.\n */\nexport interface VersionedSerializedIdCompressor {\n\treadonly _versionedSerializedIdCompressor: '8c73c57c-1cf4-4278-8915-6444cb4f6af5';\n\treadonly version: string;\n}\n\n/**\n * The serialized contents of an IdCompressor, suitable for persistence in a summary.\n */\nexport interface SerializedIdCompressor extends VersionedSerializedIdCompressor {\n\t/** The cluster capacity of this compressor */\n\treadonly clusterCapacity: number;\n\t/** The number of reserved IDs in this compressor */\n\treadonly reservedIdCount: number;\n\t/** All sessions except the local session. */\n\treadonly sessions: readonly SerializedSessionData[];\n\t/** All clusters in the compressor in the order they were created. */\n\treadonly clusters: readonly SerializedCluster[];\n\t/** All attribution IDs for all sessions */\n\treadonly attributionIds?: readonly AttributionId[];\n}\n\n/**\n * The serialized contents of an IdCompressor, suitable for persistence in a summary.\n */\nexport interface SerializedIdCompressorWithNoSession extends SerializedIdCompressor {\n\treadonly _noLocalState: '3aa2e1e8-cc28-4ea7-bc1a-a11dc3f26dfb';\n}\n\n/**\n * The serialized contents of an IdCompressor, suitable for persistence in a summary.\n */\nexport interface SerializedIdCompressorWithOngoingSession extends SerializedIdCompressor {\n\treadonly _hasLocalState: '1281acae-6d14-47e7-bc92-71c8ee0819cb';\n\t/** The session ID of the local session, by index into `sessions`. */\n\treadonly localSessionIndex: number;\n\t/** This is only present if the local session made any IDs. */\n\treadonly localState?: SerializedLocalState;\n}\n\n/**\n * Data describing a range of session-local IDs (from a remote or local session).\n *\n * A range is composed of local IDs that were generated. Some of these may have overrides.\n *\n * @example\n * Suppose an IdCompressor generated a sequence of local IDs as follows:\n * ```\n * compressor.generateLocalId()\n * compressor.generateLocalId('0093cf29-9454-4034-8940-33b1077b41c3')\n * compressor.generateLocalId()\n * compressor.generateLocalId('0ed545f8-e97e-4dc1-acf9-c4a783258bdf')\n * compressor.generateLocalId()\n * compressor.generateLocalId()\n * compressor.takeNextCreationRange()\n * ```\n * This would result in the following range:\n * ```\n * {\n * first: localId1,\n * last: localId6,\n * overrides: [[localId2, '0093cf29-9454-4034-8940-33b1077b41c3'], [localId4, '0ed545f8-e97e-4dc1-acf9-c4a783258bdf']]\n * }\n * ```\n */\nexport interface IdCreationRange {\n\treadonly sessionId: SessionId;\n\treadonly ids?: IdCreationRange.Ids;\n\treadonly attributionId?: AttributionId;\n}\n\nexport type UnackedLocalId = LocalCompressedId & OpSpaceCompressedId;\n\nexport namespace IdCreationRange {\n\texport type Ids =\n\t\t| {\n\t\t\t\treadonly first: UnackedLocalId;\n\t\t\t\treadonly last: UnackedLocalId;\n\t\t }\n\t\t| ({\n\t\t\t\treadonly first?: UnackedLocalId;\n\t\t\t\treadonly last?: UnackedLocalId;\n\t\t } & HasOverrides);\n\n\texport interface HasOverrides {\n\t\treadonly overrides: Overrides;\n\t}\n\n\texport type Override = readonly [id: UnackedLocalId, override: string];\n\texport type Overrides = readonly [Override, ...Override[]];\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export * from './MergeHealth';
|
|
|
28
28
|
export * from './TreeViewUtilities';
|
|
29
29
|
export { StringInterner } from './StringInterner';
|
|
30
30
|
export { Side, EditStatus, TreeNode, TreeNodeSequence, Payload, ConstraintEffect, Edit, ChangeInternal, InternalizedChange, ChangeNode, ChangeNode_0_0_2, EditLogSummary, FluidEditHandle, SharedTreeSummaryBase, EditWithoutId, PlaceholderTree, EditBase, HasTraits, InsertInternal, DetachInternal, BuildInternal, SetValueInternal, ConstraintInternal, BuildNodeInternal, StablePlaceInternal_0_0_2, StableRangeInternal_0_0_2, NodeData, TraitMap, ChangeTypeInternal, TraitLocationInternal_0_0_2, WriteFormat, ConstraintInternal_0_0_2, StablePlaceInternal, StableRangeInternal, BuildNodeInternal_0_0_2, BuildInternal_0_0_2, InsertInternal_0_0_2, DetachInternal_0_0_2, SetValueInternal_0_0_2, TraitLocationInternal, } from './persisted-types';
|
|
31
|
-
export { SharedTreeFactory, SharedTree, EditCommittedHandler, SequencedEditAppliedHandler, EditCommittedEventArguments, SequencedEditAppliedEventArguments, EditApplicationOutcome, ISharedTreeEvents, } from './SharedTree';
|
|
31
|
+
export { SharedTreeArgs, SharedTreeOptions, SharedTreeOptions_0_0_2, SharedTreeOptions_0_1_1, SharedTreeFactory, SharedTree, EditCommittedHandler, SequencedEditAppliedHandler, EditCommittedEventArguments, SequencedEditAppliedEventArguments, EditApplicationOutcome, ISharedTreeEvents, } from './SharedTree';
|
|
32
32
|
export * from './EventTypes';
|
|
33
33
|
export { setTrait, areRevisionViewsSemanticallyEqual, BadPlaceValidationResult, BadRangeValidationResult, PlaceValidationResult, RangeValidationResult, RangeValidationResultKind, } from './EditUtilities';
|
|
34
34
|
export { comparePayloads } from './PayloadUtilities';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AAEH;;;GAGG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACjE,OAAO,EAAE,4BAA4B,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACnF,YAAY,EACX,YAAY,EACZ,UAAU,EACV,kBAAkB,EAClB,MAAM,EACN,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,MAAM,EACN,WAAW,EACX,YAAY,EACZ,wBAAwB,EACxB,aAAa,EACb,UAAU,EACV,UAAU,EACV,aAAa,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAC5F,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EACN,IAAI,EACJ,UAAU,EACV,QAAQ,EACR,gBAAgB,EAChB,OAAO,EACP,gBAAgB,EAChB,IAAI,EACJ,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,aAAa,EACb,eAAe,EACf,QAAQ,EACR,SAAS,EACT,cAAc,EACd,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,yBAAyB,EACzB,yBAAyB,EACzB,QAAQ,EACR,QAAQ,EACR,kBAAkB,EAClB,2BAA2B,EAC3B,WAAW,EACX,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,cAAc,EACd,iBAAiB,EACjB,uBAAuB,EACvB,uBAAuB,EACvB,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,2BAA2B,EAC3B,2BAA2B,EAC3B,kCAAkC,EAClC,sBAAsB,EACtB,iBAAiB,GACjB,MAAM,cAAc,CAAC;AACtB,cAAc,cAAc,CAAC;AAC7B,OAAO,EACN,QAAQ,EACR,iCAAiC,EACjC,wBAAwB,EACxB,wBAAwB,EACxB,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EACN,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,0BAA0B,EAC1B,uBAAuB,EACvB,YAAY,GACZ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,WAAW,EACX,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,aAAa,EACb,aAAa,EACb,aAAa,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEjF;;GAEG;AACH,OAAO;AACN,wEAAwE;AACxE,sCAAsC,IAAI,4BAA4B,EACtE,sCAAsC,GACtC,MAAM,wBAAwB,CAAC;AAEhC,cAAc,eAAe,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;AAEH;;;;GAIG;AAEH;;;GAGG;AAEH,cAAc;AAEd,6CAA4C;AAAnC,0GAAA,WAAW,OAAA;AACpB,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,mCAAiE;AAAjD,gGAAA,MAAM,OAAA;AACtB,mCAAmF;AAA1E,sHAAA,4BAA4B,OAAA;AAAE,2GAAA,iBAAiB,OAAA;AAAE,gGAAA,MAAM,OAAA;AAkBhE,6CAAqD;AAA5C,mHAAA,oBAAoB,OAAA;AAI7B,uCAA4F;AAAnF,oGAAA,QAAQ,OAAA;AAAE,yGAAA,aAAa,OAAA;AAAmB,gHAAA,oBAAoB,OAAA;AACvE,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AACrB,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,uDAAqC;AACrC,gDAA8B;AAC9B,sDAAoC;AAEpC,qDAyC2B;AAxC1B,uGAAA,IAAI,OAAA;AACJ,6GAAA,UAAU,OAAA;AAIV,mHAAA,gBAAgB,OAAA;AAEhB,iHAAA,cAAc,OAAA;AAqBd,qHAAA,kBAAkB,OAAA;AAElB,8GAAA,WAAW,OAAA;AAEX,sHAAA,mBAAmB,OAAA;AACnB,sHAAA,mBAAmB,OAAA;AAQpB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;AAEH;;;;GAIG;AAEH;;;GAGG;AAEH,cAAc;AAEd,6CAA4C;AAAnC,0GAAA,WAAW,OAAA;AACpB,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,mCAAiE;AAAjD,gGAAA,MAAM,OAAA;AACtB,mCAAmF;AAA1E,sHAAA,4BAA4B,OAAA;AAAE,2GAAA,iBAAiB,OAAA;AAAE,gGAAA,MAAM,OAAA;AAkBhE,6CAAqD;AAA5C,mHAAA,oBAAoB,OAAA;AAI7B,uCAA4F;AAAnF,oGAAA,QAAQ,OAAA;AAAE,yGAAA,aAAa,OAAA;AAAmB,gHAAA,oBAAoB,OAAA;AACvE,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AACrB,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,uDAAqC;AACrC,gDAA8B;AAC9B,sDAAoC;AAEpC,qDAyC2B;AAxC1B,uGAAA,IAAI,OAAA;AACJ,6GAAA,UAAU,OAAA;AAIV,mHAAA,gBAAgB,OAAA;AAEhB,iHAAA,cAAc,OAAA;AAqBd,qHAAA,kBAAkB,OAAA;AAElB,8GAAA,WAAW,OAAA;AAEX,sHAAA,mBAAmB,OAAA;AACnB,sHAAA,mBAAmB,OAAA;AAQpB,2CAasB;AARrB,+GAAA,iBAAiB,OAAA;AACjB,wGAAA,UAAU,OAAA;AAQX,+CAA6B;AAC7B,iDAQyB;AAPxB,yGAAA,QAAQ,OAAA;AACR,kIAAA,iCAAiC,OAAA;AAGjC,sHAAA,qBAAqB,OAAA;AAErB,0HAAA,yBAAyB,OAAA;AAE1B,uDAAqD;AAA5C,mHAAA,eAAe,OAAA;AACxB,6DAa+B;AAZ9B,0HAAA,mBAAmB,OAAA;AACnB,yHAAA,kBAAkB,OAAA;AAYnB,uCASoB;AALnB,oGAAA,QAAQ,OAAA;AAMT,+CAA+D;AAAtD,4GAAA,YAAY,OAAA;AAAE,+GAAA,eAAe,OAAA;AAEtC,6CAAiF;AAAxE,0GAAA,WAAW,OAAA;AAAE,+GAAA,gBAAgB,OAAA;AAEtC;;GAEG;AACH,+DAIgC;AAH/B,wEAAwE;AACxE,oIAAA,sCAAsC,OAAgC;AACtE,8IAAA,sCAAsC,OAAA;AAGvC,gDAA8B","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Fluid DDS storing a tree.\n *\n * @packageDocumentation\n */\n\n/**\n * This file represents the public API. Consumers of this package will not see exported modules unless they are enumerated here.\n * Removing / editing existing exports here will often indicate a breaking change, so please be cognizant of changes made here.\n */\n\n// API Exports\n\nexport { initialTree } from './InitialTree';\nexport { TreeNodeHandle } from './TreeNodeHandle';\nexport { Delta, Forest, ForestNode, ParentData } from './Forest';\nexport { sharedTreeAssertionErrorType, isSharedTreeEvent, Result } from './Common';\nexport type {\n\tCompressedId,\n\tDefinition,\n\tDetachedSequenceId,\n\tEditId,\n\tInternedStringId,\n\tFinalCompressedId,\n\tLocalCompressedId,\n\tNodeId,\n\tNodeIdBrand,\n\tStableNodeId,\n\tSessionSpaceCompressedId,\n\tSessionUnique,\n\tTraitLabel,\n\tUuidString,\n\tAttributionId,\n} from './Identifiers';\nexport { isDetachedSequenceId } from './Identifiers';\nexport type { OrderedEditSet, EditHandle } from './EditLog';\nexport { LogViewer } from './LogViewer';\nexport { Revision } from './RevisionValueCache';\nexport { Checkout, CheckoutEvent, ICheckoutEvents, EditValidationResult } from './Checkout';\nexport { LazyCheckout } from './LazyCheckout';\nexport { EagerCheckout } from './EagerCheckout';\nexport * from './ReconciliationPath';\nexport * from './MergeHealth';\nexport * from './TreeViewUtilities';\nexport { StringInterner } from './StringInterner';\nexport {\n\tSide,\n\tEditStatus,\n\tTreeNode,\n\tTreeNodeSequence,\n\tPayload,\n\tConstraintEffect,\n\tEdit,\n\tChangeInternal,\n\tInternalizedChange,\n\tChangeNode,\n\tChangeNode_0_0_2,\n\tEditLogSummary,\n\tFluidEditHandle,\n\tSharedTreeSummaryBase,\n\tEditWithoutId,\n\tPlaceholderTree,\n\tEditBase,\n\tHasTraits,\n\tInsertInternal,\n\tDetachInternal,\n\tBuildInternal,\n\tSetValueInternal,\n\tConstraintInternal,\n\tBuildNodeInternal,\n\tStablePlaceInternal_0_0_2,\n\tStableRangeInternal_0_0_2,\n\tNodeData,\n\tTraitMap,\n\tChangeTypeInternal,\n\tTraitLocationInternal_0_0_2,\n\tWriteFormat,\n\tConstraintInternal_0_0_2,\n\tStablePlaceInternal,\n\tStableRangeInternal,\n\tBuildNodeInternal_0_0_2,\n\tBuildInternal_0_0_2,\n\tInsertInternal_0_0_2,\n\tDetachInternal_0_0_2,\n\tSetValueInternal_0_0_2,\n\tTraitLocationInternal,\n} from './persisted-types';\nexport {\n\tSharedTreeArgs,\n\tSharedTreeOptions,\n\tSharedTreeOptions_0_0_2,\n\tSharedTreeOptions_0_1_1,\n\tSharedTreeFactory,\n\tSharedTree,\n\tEditCommittedHandler,\n\tSequencedEditAppliedHandler,\n\tEditCommittedEventArguments,\n\tSequencedEditAppliedEventArguments,\n\tEditApplicationOutcome,\n\tISharedTreeEvents,\n} from './SharedTree';\nexport * from './EventTypes';\nexport {\n\tsetTrait,\n\tareRevisionViewsSemanticallyEqual,\n\tBadPlaceValidationResult,\n\tBadRangeValidationResult,\n\tPlaceValidationResult,\n\tRangeValidationResult,\n\tRangeValidationResultKind,\n} from './EditUtilities';\nexport { comparePayloads } from './PayloadUtilities';\nexport {\n\tTransactionInternal,\n\tGenericTransaction,\n\tGenericTransactionPolicy,\n\tEditingResult,\n\tEditingResultBase,\n\tFailedEditingResult,\n\tValidEditingResult,\n\tTransactionState,\n\tTransactionFailure,\n\tSucceedingTransactionState,\n\tFailingTransactionState,\n\tChangeResult,\n} from './TransactionInternal';\nexport {\n\tNodeInTrait,\n\tPlaceIndex,\n\tTreeViewNode,\n\tTreeView,\n\tTraitNodeIndex,\n\tTreeViewPlace,\n\tTreeViewRange,\n\tTraitLocation,\n} from './TreeView';\nexport { RevisionView, TransactionView } from './RevisionView';\nexport { NodeIdContext, NodeIdGenerator, NodeIdConverter } from './NodeIdUtilities';\nexport { Transaction, TransactionEvent, TransactionEvents } from './Transaction';\n\n/**\n * TODO:#61413: Publish test utilities from a separate test package\n */\nexport {\n\t/** @deprecated Use `getSerializedUploadedEditChunkContents` instead. */\n\tgetSerializedUploadedEditChunkContents as getUploadedEditChunkContents,\n\tgetSerializedUploadedEditChunkContents,\n} from './SummaryTestUtilities';\n\nexport * from './ChangeTypes';\n"]}
|
package/lib/Forest.js
CHANGED
|
@@ -291,7 +291,7 @@ export class Forest {
|
|
|
291
291
|
const parent = this.get(node.parentId);
|
|
292
292
|
const trait = parent.traits.get(node.traitParent);
|
|
293
293
|
assert(trait !== undefined);
|
|
294
|
-
assert(trait.
|
|
294
|
+
assert(trait.includes(node.identifier), 'node is parented incorrectly');
|
|
295
295
|
}
|
|
296
296
|
for (const trait of node.traits.values()) {
|
|
297
297
|
assert(trait.length > 0, 'trait is present but empty');
|
package/lib/Forest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Forest.js","sourceRoot":"","sources":["../src/Forest.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,cAAc,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,qBAAqB,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEpG,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAmBrD;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAgB;IACpD,MAAM,YAAY,GAAG,IAAgD,CAAC;IACtE,MAAM,SAAS,GAAG,YAAY,CAAC,QAAQ,KAAK,SAAS,CAAC;IACtD,MAAM,cAAc,GAAG,YAAY,CAAC,WAAW,KAAK,SAAS,CAAC;IAC9D,MAAM,CAAC,SAAS,KAAK,cAAc,EAAE,kEAAkE,CAAC,CAAC;IACzG,OAAO,SAAS,CAAC;AAClB,CAAC;AAmCD;;;;;GAKG;AACH,MAAM,OAAO,MAAM;IAuBlB,YAAoB,IAA4B;QAC/C,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;YAC7B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YACxB,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,CAAC;SACpD;aAAM;YACN,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAqB,SAAS,EAAE,oBAAoB,CAAC,CAAC;YAC5E,IAAI,CAAC,mBAAmB,GAAG,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,KAAK,CAAC;SACzC;QACD,IAAI,IAAI,CAAC,mBAAmB,EAAE;YAC7B,IAAI,CAAC,gBAAgB,EAAE,CAAC;SACxB;IACF,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,MAAM,CAAC,mBAAmB,GAAG,KAAK;QAC/C,OAAO,IAAI,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,IAAW,IAAI;QACd,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACI,GAAG,CAAC,KAA2B;QACrC,MAAM,QAAQ,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;QAC5B,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAExC,+HAA+H;QAC/H,yHAAyH;QAEzH,MAAM,aAAa,GAAG,IAAI,GAAG,EAAsB,CAAC,CAAC,qEAAqE;QAE1H,6HAA6H;QAC7H,0HAA0H;QAC1H,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE;YAC5B,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;YAC5B,KAAK,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE;gBAC9C,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,sDAAsD,CAAC,CAAC;gBACjF,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE;oBAC5B,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;oBACxC,IAAI,KAAK,KAAK,SAAS,EAAE;wBACxB,0EAA0E;wBAC1E,MAAM,CAAC,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,uCAAuC,CAAC,CAAC;wBAC9E,MAAM,aAAa,GAAG;4BACrB,UAAU,EAAE,KAAK,CAAC,UAAU;4BAC5B,UAAU,EAAE,KAAK,CAAC,UAAU;4BAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;4BACpB,QAAQ,EAAE,UAAU;4BACpB,WAAW,EAAE,UAAU;yBACvB,CAAC;wBACF,qBAAqB,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;wBACvD,yDAAyD;wBACzD,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;qBACzC;yBAAM;wBACN,yFAAyF;wBACzF,aAAa,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;qBAC9E;iBACD;aACD;SACD;QAED,8FAA8F;QAC9F,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE;YAC5B,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACtD,MAAM,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,2CAA2C,CAAC,CAAC;YACxF,IAAI,UAAU,KAAK,SAAS,EAAE;gBAC7B,0HAA0H;gBAC1H,MAAM,KAAK,mBACV,UAAU,EAAE,IAAI,CAAC,UAAU,EAC3B,UAAU,EAAE,IAAI,CAAC,UAAU,EAC3B,MAAM,EAAE,IAAI,CAAC,MAAM,IAChB,UAAU,CACb,CAAC;gBACF,qBAAqB,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;gBAC9C,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;aACzC;iBAAM;gBACN,2EAA2E;gBAC3E,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;aACxC;SACD;QAED,OAAO,IAAI,MAAM,CAAC;YACjB,KAAK,EAAE,YAAY;YACnB,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;SAC7C,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACI,qBAAqB,CAC3B,QAAgB,EAChB,KAAiB,EACjB,KAAa,EACb,QAA2B;;QAE3B,MAAM,CAAC,KAAK,IAAI,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,CAAC,UAAU,EAAE,wDAAwD,CAAC,CAAC;QAC7E,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAA,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,mCAAI,EAAE,CAAC;QACtC,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;QAEtD,+CAA+C;QAC/C,wHAAwH;QACxH,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;YAC1B,OAAO,IAAI,CAAC;SACZ;QACD,MAAM,WAAW,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,QAAQ,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACnF,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAC/B,YAAY,CAAC,GAAG,CAAC,QAAQ,kCAAO,UAAU,KAAE,MAAM,IAAG,CAAC;QAEtD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;YAC/B,YAAY,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBACvD,MAAM,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,+CAA+C,CAAC,CAAC;gBAClF,MAAM,QAAQ,GAAkC;oBAC/C,KAAK,kCACD,CAAC,KACJ,QAAQ,EACR,WAAW,EAAE,KAAK,GAClB;iBACD,CAAC;gBACF,OAAO,QAAQ,CAAC;YACjB,CAAC,CAAC,CAAC;SACH;QAED,OAAO,IAAI,MAAM,CAAC;YACjB,KAAK,EAAE,YAAY;YACnB,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;SAC7C,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACI,qBAAqB,CAC3B,QAAgB,EAChB,KAAiB,EACjB,UAAkB,EAClB,QAAgB;;QAEhB,MAAM,CAAC,UAAU,IAAI,CAAC,IAAI,QAAQ,IAAI,UAAU,EAAE,4BAA4B,CAAC,CAAC;QAChF,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,CAAC,UAAU,EAAE,wDAAwD,CAAC,CAAC;QAC7E,IAAI,UAAU,KAAK,QAAQ,EAAE;YAC5B,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;SACtC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAA,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,mCAAI,EAAE,CAAC;QACtC,MAAM,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAC;QAC/D,MAAM,QAAQ,GAAa,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC7D,MAAM,WAAW,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC9E,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC;QAC7C,IAAI,WAAW,EAAE;YAChB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;SACrB;aAAM;YACN,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;SAC/B;QAED,YAAY,CAAC,GAAG,CAAC,QAAQ,kCAAO,UAAU,KAAE,MAAM,IAAG,CAAC;QACtD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;YAC/B,YAAY,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBACvD,MAAM,QAAQ,GAA0B;oBACvC,KAAK,EAAE;wBACN,UAAU,EAAE,CAAC,CAAC,UAAU;wBACxB,UAAU,EAAE,CAAC,CAAC,UAAU;wBACxB,MAAM,EAAE,CAAC,CAAC,MAAM;qBAChB;iBACD,CAAC;gBACF,qBAAqB,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;gBACpD,OAAO,QAAQ,CAAC;YACjB,CAAC,CAAC,CAAC;SACH;QAED,OAAO;YACN,MAAM,EAAE,IAAI,MAAM,CAAC;gBAClB,KAAK,EAAE,YAAY;gBACnB,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;aAC7C,CAAC;YACF,QAAQ;SACR,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,kDAAkD;IAC3C,QAAQ,CAAC,MAAc,EAAE,KAAqB;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,CAAC,IAAI,EAAE,sDAAsD,CAAC,CAAC;QACrE,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,OAAO,qBAAQ,IAAI,CAAE,CAAC;QAC5B,IAAI,KAAK,KAAK,IAAI,EAAE;YACnB,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC;SACxB;aAAM;YACN,OAAO,OAAO,CAAC,OAAO,CAAC;SACvB;QACD,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,OAAO,IAAI,MAAM,CAAC;YACjB,KAAK,EAAE,YAAY;YACnB,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;SAC7C,CAAC,CAAC;IACJ,CAAC;IAED;;OAEG;IACI,GAAG,CAAC,EAAU;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED;;OAEG;IACI,GAAG,CAAC,EAAU;;QACpB,OAAO,MAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,mCAAI,IAAI,CAAC,kBAAkB,CAAC,CAAC;IACvD,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,EAAU;QACvB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,GAAqB,EAAE,cAAuB;QAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE;YACrB,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,EAAE,EAAE,cAAc,CAAC,CAAC;SACvD;QAED,OAAO,IAAI,MAAM,CAAC;YACjB,KAAK,EAAE,YAAY;YACnB,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;SAC7C,CAAC,CAAC;IACJ,CAAC;IAEO,eAAe,CAAC,YAAuC,EAAE,EAAU,EAAE,cAAuB;;QACnG,MAAM,IAAI,GAAG,MAAA,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,mCAAI,IAAI,CAAC,2BAA2B,CAAC,CAAC;QACvE,MAAM,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,kCAAkC,CAAC,CAAC;QACxE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE;YACzC,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE;gBAC5B,YAAY,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;oBACvD,MAAM,QAAQ,GAA0B;wBACvC,KAAK,EAAE;4BACN,UAAU,EAAE,CAAC,CAAC,UAAU;4BACxB,UAAU,EAAE,CAAC,CAAC,UAAU;4BACxB,MAAM,EAAE,CAAC,CAAC,MAAM;yBAChB;qBACD,CAAC;oBACF,qBAAqB,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;oBACpD,OAAO,QAAQ,CAAC;gBACjB,CAAC,CAAC,CAAC;gBAEH,IAAI,cAAc,EAAE;oBACnB,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;iBAC5D;aACD;SACD;IACF,CAAC;IAED;;;OAGG;IACI,gBAAgB;;QACtB,MAAM,eAAe,GAAG,IAAI,GAAG,CAAS,EAAE,CAAC,CAAC;QAC5C,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE;YAC/D,IAAI,oBAAoB,CAAC,IAAI,CAAC,EAAE;gBAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACvC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBAClD,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;gBAC5B,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,8BAA8B,CAAC,CAAC;aAC5E;YAED,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE;gBACzC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,4BAA4B,CAAC,CAAC;gBACvD,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE;oBAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;oBACtC,MAAM,CAAC,KAAK,EAAE,iCAAiC,CAAC,CAAC;oBACjD,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,uBAAuB,CAAC,CAAC;oBAC7D,MAAM,CAAC,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,UAAU,EAAE,mCAAmC,CAAC,CAAC;oBAChF,MAAM,CACL,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,EAC7B,oEAAoE,CACpE,CAAC;oBACF,MAAM,CACL,CAAC,MAAA,KAAK,CAAC,QAAQ,mCAAI,IAAI,CAAC,yCAAyC,CAAC,CAAC,KAAK,MAAM,EAC9E,4BAA4B,CAC5B,CAAC;oBACF,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;iBAC7B;aACD;SACD;IACF,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,EAAU;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACjC,IAAI,KAAK,KAAK,SAAS,EAAE;YACxB,IAAI,CAAC,kBAAkB,CAAC,CAAC;SACzB;QAED,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC5D,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;IACrE,CAAC;IAED;;OAEG;IACI,YAAY,CAAC,EAAU;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACjC,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE;YACxD,OAAO,SAAS,CAAC;SACjB;QAED,OAAO;YACN,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,WAAW,EAAE,KAAK,CAAC,WAAW;SAC9B,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,MAAc;QAC3B,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,EAAE;YACnD,OAAO,IAAI,CAAC;SACZ;QAED,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE;YAC9B,OAAO,KAAK,CAAC;SACb;QAED,OAAO,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;IACpE,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,MAAc;QAC1B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,WAAW,CACrB,MAAM,CAAC,KAAK,EACZ,CAAC,EAAE,EAAE,EAAE;YACN,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC,EACD,CAAC,EAAE,EAAE,EAAE;YACN,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB,CAAC,EACD,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;YAC3B,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE;gBAC7C,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;aACjB;QACF,CAAC,CACD,CAAC;QACF,OAAO;YACN,OAAO;YACP,KAAK;YACL,OAAO;SACP,CAAC;IACH,CAAC;CACD;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAiB,EAAE,KAAiB;IACtE,IAAI,KAAK,KAAK,KAAK,EAAE;QACpB,OAAO,IAAI,CAAC;KACZ;IAED,IAAI,KAAK,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,EAAE;QAC1C,OAAO,KAAK,CAAC;KACb;IAED,IAAI,KAAK,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,EAAE;QAC1C,OAAO,KAAK,CAAC;KACb;IAED,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE;QACnD,OAAO,KAAK,CAAC;KACb;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE;QAC5C,OAAO,KAAK,CAAC;KACb;IAED,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,MAAM,EAAE;QAClC,MAAM,CAAC,WAAW,EAAE,aAAa,CAAC,GAAG,MAAM,CAAC;QAC5C,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACpD,IAAI,CAAC,aAAa,EAAE;YACnB,OAAO,KAAK,CAAC;SACb;QAED,IAAI,aAAa,CAAC,MAAM,KAAK,aAAa,CAAC,MAAM,EAAE;YAClD,OAAO,KAAK,CAAC;SACb;QAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC9C,IAAI,aAAa,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,EAAE;gBAC1C,OAAO,KAAK,CAAC;aACb;SACD;KACD;IAED,OAAO,IAAI,CAAC;AACb,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport BTree from 'sorted-btree';\nimport { fail, assert, copyPropertyIfDefined, compareBtrees, compareFiniteNumbers } from './Common';\nimport { NodeId, TraitLabel } from './Identifiers';\nimport { comparePayloads } from './PayloadUtilities';\nimport { NodeData, Payload } from './persisted-types';\n\n/**\n * A node that can be contained within a Forest\n *\n * @public\n */\nexport interface ForestNode extends NodeData<NodeId> {\n\treadonly traits: ReadonlyMap<TraitLabel, readonly NodeId[]>;\n}\n\n/**\n * A node within a Forest that has a parent (and is therefore not the root node)\n *\n * @public\n */\nexport interface ParentedForestNode extends ForestNode, ParentData {}\n\n/**\n * Check whether or not the given node in a forest is parented\n *\n * @public\n */\nexport function isParentedForestNode(node: ForestNode): node is ParentedForestNode {\n\tconst parentedNode = node as ForestNode & Partial<ParentedForestNode>;\n\tconst hasParent = parentedNode.parentId !== undefined;\n\tconst hasTraitParent = parentedNode.traitParent !== undefined;\n\tassert(hasParent === hasTraitParent, 'node must have either both parent and traitParent set or neither');\n\treturn hasParent;\n}\n\n/**\n * Information about a ForestNode's parent\n *\n * @public\n */\nexport interface ParentData {\n\treadonly parentId: NodeId;\n\treadonly traitParent: TraitLabel;\n}\n\n/**\n * Differences from one forest to another.\n */\nexport interface Delta<NodeId> {\n\t/**\n\t * Nodes whose content changed.\n\t */\n\treadonly changed: readonly NodeId[];\n\t/**\n\t * Nodes that were added.\n\t */\n\treadonly added: readonly NodeId[];\n\t/**\n\t * Nodes that were removed.\n\t */\n\treadonly removed: readonly NodeId[];\n}\n\ninterface ForestState {\n\tnodes: BTree<NodeId, ForestNode>;\n\texpensiveValidation: boolean;\n}\n\n/**\n * An immutable forest of ForestNode.\n * Enforces single parenting, and allows querying the parent.\n *\n * @public\n */\nexport class Forest {\n\t/**\n\t * Contains the nodes in the forest.\n\t * Used as an immutable data-structure: must not be modified.\n\t */\n\tprivate readonly nodes: BTree<NodeId, ForestNode>;\n\n\t/**\n\t * If true, consistency checks will be applied after forest operations.\n\t */\n\tprivate readonly expensiveValidation: boolean;\n\n\t/**\n\t * Caller must ensure provided BTrees are not modified.\n\t * Will not modify the BTrees.\n\t */\n\tprivate constructor(data: ForestState);\n\n\t/**\n\t * Construct a new forest without reusing nodes from a previous one.\n\t */\n\tprivate constructor(expensiveValidation: boolean);\n\n\tprivate constructor(data?: ForestState | boolean) {\n\t\tif (typeof data === 'object') {\n\t\t\tthis.nodes = data.nodes;\n\t\t\tthis.expensiveValidation = data.expensiveValidation;\n\t\t} else {\n\t\t\tthis.nodes = new BTree<NodeId, ForestNode>(undefined, compareFiniteNumbers);\n\t\t\tthis.expensiveValidation = data ?? false;\n\t\t}\n\t\tif (this.expensiveValidation) {\n\t\t\tthis.assertConsistent();\n\t\t}\n\t}\n\n\t/**\n\t * Creates a new Forest.\n\t */\n\tpublic static create(expensiveValidation = false): Forest {\n\t\treturn new Forest(expensiveValidation);\n\t}\n\n\t/**\n\t * Returns the number of nodes in the forest.\n\t */\n\tpublic get size(): number {\n\t\treturn this.nodes.size;\n\t}\n\n\t/**\n\t * Adds the supplied nodes to the forest. The nodes' IDs must be unique in the forest.\n\t * @param nodes - the sequence of nodes to add to the forest. If any of them have children which exist in the forest already, those\n\t * children will be parented. Any trait arrays present in a node must be non-empty. The nodes may be provided in any order.\n\t */\n\tpublic add(nodes: Iterable<ForestNode>): Forest {\n\t\tconst newNodes = [...nodes];\n\t\tconst mutableNodes = this.nodes.clone();\n\n\t\t// This method iterates through the supplied nodes in two passes, first looking only at children and second actually adding the\n\t\t// nodes. This allows nodes to be passed in any order, e.g. a parent followed by a child or a child followed by a parent.\n\n\t\tconst childToParent = new Map<NodeId, ParentData>(); // Temporarily records the parentage of children that don't exist yet\n\n\t\t// First, inspect the children of each node. If the child is already in the forest, update its parentage. If it is not in the\n\t\t// forest, it may be about to be added in the second loop below so record its parentage temporarily for when that happens.\n\t\tfor (const node of newNodes) {\n\t\t\tconst { identifier } = node;\n\t\t\tfor (const [traitLabel, trait] of node.traits) {\n\t\t\t\tassert(trait.length > 0, 'any trait arrays present in a node must be non-empty');\n\t\t\t\tfor (const childId of trait) {\n\t\t\t\t\tconst child = mutableNodes.get(childId);\n\t\t\t\t\tif (child !== undefined) {\n\t\t\t\t\t\t// A child already exists in the forest, and its parent is now being added\n\t\t\t\t\t\tassert(!isParentedForestNode(child), 'can not give a child multiple parents');\n\t\t\t\t\t\tconst parentedChild = {\n\t\t\t\t\t\t\tdefinition: child.definition,\n\t\t\t\t\t\t\tidentifier: child.identifier,\n\t\t\t\t\t\t\ttraits: child.traits,\n\t\t\t\t\t\t\tparentId: identifier,\n\t\t\t\t\t\t\ttraitParent: traitLabel,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tcopyPropertyIfDefined(child, parentedChild, 'payload');\n\t\t\t\t\t\t// Overwrite the existing child with its parented version\n\t\t\t\t\t\tmutableNodes.set(childId, parentedChild);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// The child hasn't been added yet, so record its parentage to use when it is added below\n\t\t\t\t\t\tchildToParent.set(childId, { parentId: identifier, traitParent: traitLabel });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Now add each node to the forest and apply any parentage information that was recorded above\n\t\tfor (const node of newNodes) {\n\t\t\tconst parentData = childToParent.get(node.identifier);\n\t\t\tassert(!mutableNodes.has(node.identifier), 'can not add node with already existing id');\n\t\t\tif (parentData !== undefined) {\n\t\t\t\t// This is a child whom we haven't added yet, but whose parent we already added above. Supply the recorded parentage info.\n\t\t\t\tconst child = {\n\t\t\t\t\tdefinition: node.definition,\n\t\t\t\t\tidentifier: node.identifier,\n\t\t\t\t\ttraits: node.traits,\n\t\t\t\t\t...parentData,\n\t\t\t\t};\n\t\t\t\tcopyPropertyIfDefined(node, child, 'payload');\n\t\t\t\tmutableNodes.set(node.identifier, child);\n\t\t\t} else {\n\t\t\t\t// This is a node that has no parent. Add it with no parentage information.\n\t\t\t\tmutableNodes.set(node.identifier, node);\n\t\t\t}\n\t\t}\n\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\t/**\n\t * Parents a set of nodes already in the forest at a specified location within a trait.\n\t * @param parentId - the id of the parent under which to insert the new nodes\n\t * @param label - the label of the trait under which to insert the new nodes\n\t * @param index - the index in the trait after which to insert the new nodes\n\t * @param childIds - the ids of the nodes to insert\n\t */\n\tpublic attachRangeOfChildren(\n\t\tparentId: NodeId,\n\t\tlabel: TraitLabel,\n\t\tindex: number,\n\t\tchildIds: readonly NodeId[]\n\t): Forest {\n\t\tassert(index >= 0, 'invalid attach index');\n\t\tconst parentNode = this.nodes.get(parentId);\n\t\tassert(parentNode, 'can not insert children under node that does not exist');\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tconst traits = new Map(parentNode.traits);\n\t\tconst trait = traits.get(label) ?? [];\n\t\tassert(index <= trait.length, 'invalid attach index');\n\n\t\t// If there is nothing to insert, return early.\n\t\t// This is good for performance, but also avoids an edge case where an empty trait could be created (which is an error).\n\t\tif (childIds.length === 0) {\n\t\t\treturn this;\n\t\t}\n\t\tconst newChildren = [...trait.slice(0, index), ...childIds, ...trait.slice(index)];\n\t\ttraits.set(label, newChildren);\n\t\tmutableNodes.set(parentId, { ...parentNode, traits });\n\n\t\tfor (const childId of childIds) {\n\t\t\tmutableNodes.editRange(childId, childId, true, (_, n) => {\n\t\t\t\tassert(!isParentedForestNode(n), 'can not attach node that already has a parent');\n\t\t\t\tconst breakVal: { value: ParentedForestNode } = {\n\t\t\t\t\tvalue: {\n\t\t\t\t\t\t...n,\n\t\t\t\t\t\tparentId,\n\t\t\t\t\t\ttraitParent: label,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\treturn breakVal;\n\t\t\t});\n\t\t}\n\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\t/**\n\t * Detaches a range of nodes from their parent. The detached nodes remain in the `Forest`.\n\t * @param parentId - the id of the parent from which to detach the nodes\n\t * @param label - the label of the trait from which to detach the nodes\n\t * @param startIndex - the index of the first node in the range to detach\n\t * @param endIndex - the index after the last node in the range to detach\n\t * @returns a new `Forest` with the nodes detached, and a list of the ids of the nodes that were detached\n\t */\n\tpublic detachRangeOfChildren(\n\t\tparentId: NodeId,\n\t\tlabel: TraitLabel,\n\t\tstartIndex: number,\n\t\tendIndex: number\n\t): { forest: Forest; detached: readonly NodeId[] } {\n\t\tassert(startIndex >= 0 && endIndex >= startIndex, 'invalid detach index range');\n\t\tconst parentNode = this.nodes.get(parentId);\n\t\tassert(parentNode, 'can not detach children under node that does not exist');\n\t\tif (startIndex === endIndex) {\n\t\t\treturn { forest: this, detached: [] };\n\t\t}\n\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tconst traits = new Map(parentNode.traits);\n\t\tconst trait = traits.get(label) ?? [];\n\t\tassert(endIndex <= trait.length, 'invalid detach index range');\n\t\tconst detached: NodeId[] = trait.slice(startIndex, endIndex);\n\t\tconst newChildren = [...trait.slice(0, startIndex), ...trait.slice(endIndex)];\n\t\tconst deleteTrait = newChildren.length === 0;\n\t\tif (deleteTrait) {\n\t\t\ttraits.delete(label);\n\t\t} else {\n\t\t\ttraits.set(label, newChildren);\n\t\t}\n\n\t\tmutableNodes.set(parentId, { ...parentNode, traits });\n\t\tfor (const childId of detached) {\n\t\t\tmutableNodes.editRange(childId, childId, true, (_, n) => {\n\t\t\t\tconst breakVal: { value: ForestNode } = {\n\t\t\t\t\tvalue: {\n\t\t\t\t\t\tdefinition: n.definition,\n\t\t\t\t\t\tidentifier: n.identifier,\n\t\t\t\t\t\ttraits: n.traits,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tcopyPropertyIfDefined(n, breakVal.value, 'payload');\n\t\t\t\treturn breakVal;\n\t\t\t});\n\t\t}\n\n\t\treturn {\n\t\t\tforest: new Forest({\n\t\t\t\tnodes: mutableNodes,\n\t\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t\t}),\n\t\t\tdetached,\n\t\t};\n\t}\n\n\t/**\n\t * Replaces a node's value. The node must exist in this `Forest`.\n\t * @param nodeId - the id of the node\n\t * @param value - the new value\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic setValue(nodeId: NodeId, value: Payload | null): Forest {\n\t\tconst node = this.nodes.get(nodeId);\n\t\tassert(node, 'can not replace payload for node that does not exist');\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tconst newNode = { ...node };\n\t\tif (value !== null) {\n\t\t\tnewNode.payload = value;\n\t\t} else {\n\t\t\tdelete newNode.payload;\n\t\t}\n\t\tmutableNodes.set(nodeId, newNode);\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\t/**\n\t * @returns true if the node associated with `id` exists in this forest, otherwise false\n\t */\n\tpublic has(id: NodeId): boolean {\n\t\treturn this.nodes.has(id);\n\t}\n\n\t/**\n\t * @returns the node associated with `id`. Should not be used if there is no node with the provided id.\n\t */\n\tpublic get(id: NodeId): ForestNode {\n\t\treturn this.nodes.get(id) ?? fail('NodeId not found');\n\t}\n\n\t/**\n\t * @returns the node associated with `id`, or undefined if there is none\n\t */\n\tpublic tryGet(id: NodeId): ForestNode | undefined {\n\t\treturn this.nodes.get(id);\n\t}\n\n\t/**\n\t * Deletes every node in ids (each of which must be unparented)\n\t * @param ids - The IDs of the nodes to delete.\n\t * @param deleteChildren - If true, recursively deletes descendants. Otherwise, leaves children unparented.\n\t */\n\tpublic delete(ids: Iterable<NodeId>, deleteChildren: boolean): Forest {\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tfor (const id of ids) {\n\t\t\tthis.deleteRecursive(mutableNodes, id, deleteChildren);\n\t\t}\n\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\tprivate deleteRecursive(mutableNodes: BTree<NodeId, ForestNode>, id: NodeId, deleteChildren: boolean): void {\n\t\tconst node = mutableNodes.get(id) ?? fail('node to delete must exist');\n\t\tassert(!isParentedForestNode(node), 'deleted nodes must be unparented');\n\t\tmutableNodes.delete(id);\n\t\tfor (const trait of node.traits.values()) {\n\t\t\tfor (const childId of trait) {\n\t\t\t\tmutableNodes.editRange(childId, childId, true, (_, n) => {\n\t\t\t\t\tconst breakVal: { value: ForestNode } = {\n\t\t\t\t\t\tvalue: {\n\t\t\t\t\t\t\tdefinition: n.definition,\n\t\t\t\t\t\t\tidentifier: n.identifier,\n\t\t\t\t\t\t\ttraits: n.traits,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tcopyPropertyIfDefined(n, breakVal.value, 'payload');\n\t\t\t\t\treturn breakVal;\n\t\t\t\t});\n\n\t\t\t\tif (deleteChildren) {\n\t\t\t\t\tthis.deleteRecursive(mutableNodes, childId, deleteChildren);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks that the metadata is correct, and the items form a forest.\n\t * This is an expensive O(map size) operation.\n\t */\n\tpublic assertConsistent(): void {\n\t\tconst checkedChildren = new Set<NodeId>([]);\n\t\tfor (const [nodeId, node] of this.nodes.entries(undefined, [])) {\n\t\t\tif (isParentedForestNode(node)) {\n\t\t\t\tconst parent = this.get(node.parentId);\n\t\t\t\tconst trait = parent.traits.get(node.traitParent);\n\t\t\t\tassert(trait !== undefined);\n\t\t\t\tassert(trait.indexOf(node.identifier) >= 0, 'node is parented incorrectly');\n\t\t\t}\n\n\t\t\tfor (const trait of node.traits.values()) {\n\t\t\t\tassert(trait.length > 0, 'trait is present but empty');\n\t\t\t\tfor (const childId of trait) {\n\t\t\t\t\tconst child = this.nodes.get(childId);\n\t\t\t\t\tassert(child, 'child in trait is not in forest');\n\t\t\t\t\tassert(isParentedForestNode(child), 'child is not parented');\n\t\t\t\t\tassert(child.parentId === node.identifier, 'child parent pointer is incorrect');\n\t\t\t\t\tassert(\n\t\t\t\t\t\t!checkedChildren.has(childId),\n\t\t\t\t\t\t'the item tree tree must not contain cycles or multi-parented nodes'\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\t(child.parentId ?? fail('each node must have associated metadata')) === nodeId,\n\t\t\t\t\t\t'cached parent is incorrect'\n\t\t\t\t\t);\n\t\t\t\t\tcheckedChildren.add(childId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @returns the parent of `id`. Should not be used if there is no node with id or if id refers to the root node.\n\t */\n\tpublic getParent(id: NodeId): ParentData {\n\t\tconst child = this.nodes.get(id);\n\t\tif (child === undefined) {\n\t\t\tfail('NodeId not found');\n\t\t}\n\n\t\tassert(isParentedForestNode(child), 'Node is not parented');\n\t\treturn { parentId: child.parentId, traitParent: child.traitParent };\n\t}\n\n\t/**\n\t * @returns undefined iff root, otherwise the parent of `id`.\n\t */\n\tpublic tryGetParent(id: NodeId): ParentData | undefined {\n\t\tconst child = this.nodes.get(id);\n\t\tif (child === undefined || !isParentedForestNode(child)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tparentId: child.parentId,\n\t\t\ttraitParent: child.traitParent,\n\t\t};\n\t}\n\n\t/**\n\t * Compares two forests for equality.\n\t * @param forest - the other forest to compare to this one\n\t * @param comparator - a function which returns true if two objects of type ForestNode are equivalent, false otherwise\n\t * @returns true iff the forests are equal.\n\t */\n\tpublic equals(forest: Forest): boolean {\n\t\tif (this === forest || this.nodes === forest.nodes) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (forest.size !== this.size) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn compareBtrees(this.nodes, forest.nodes, compareForestNodes);\n\t}\n\n\t/**\n\t * Calculate the difference between two forests.\n\t * @param forest - the other forest to compare to this one\n\t * @param comparator - a function which returns true if two objects of type ForestNode are equivalent, false otherwise\n\t * @returns A {@link Delta} listing which nodes must be changed, added, and removed to get from `this` to `forest`.\n\t */\n\tpublic delta(forest: Forest): Delta<NodeId> {\n\t\tconst changed: NodeId[] = [];\n\t\tconst removed: NodeId[] = [];\n\t\tconst added: NodeId[] = [];\n\t\tthis.nodes.diffAgainst(\n\t\t\tforest.nodes,\n\t\t\t(id) => {\n\t\t\t\tremoved.push(id);\n\t\t\t},\n\t\t\t(id) => {\n\t\t\t\tadded.push(id);\n\t\t\t},\n\t\t\t(id, nodeThis, nodeOther) => {\n\t\t\t\tif (!compareForestNodes(nodeThis, nodeOther)) {\n\t\t\t\t\tchanged.push(id);\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t\treturn {\n\t\t\tchanged,\n\t\t\tadded,\n\t\t\tremoved,\n\t\t};\n\t}\n}\n\n/**\n * @returns true iff two `ForestNodes` are equivalent.\n * May return false for nodes they contain equivalent payloads encoded differently.\n */\nexport function compareForestNodes(nodeA: ForestNode, nodeB: ForestNode): boolean {\n\tif (nodeA === nodeB) {\n\t\treturn true;\n\t}\n\n\tif (nodeA.identifier !== nodeB.identifier) {\n\t\treturn false;\n\t}\n\n\tif (nodeA.definition !== nodeB.definition) {\n\t\treturn false;\n\t}\n\n\tif (!comparePayloads(nodeA.payload, nodeB.payload)) {\n\t\treturn false;\n\t}\n\n\tif (nodeA.traits.size !== nodeB.traits.size) {\n\t\treturn false;\n\t}\n\n\tfor (const traitA of nodeA.traits) {\n\t\tconst [traitLabelA, nodeSequenceA] = traitA;\n\t\tconst nodeSequenceB = nodeB.traits.get(traitLabelA);\n\t\tif (!nodeSequenceB) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (nodeSequenceA.length !== nodeSequenceB.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (let i = 0; i < nodeSequenceA.length; i++) {\n\t\t\tif (nodeSequenceA[i] !== nodeSequenceB[i]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Forest.js","sourceRoot":"","sources":["../src/Forest.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport BTree from 'sorted-btree';\nimport { fail, assert, copyPropertyIfDefined, compareBtrees, compareFiniteNumbers } from './Common';\nimport { NodeId, TraitLabel } from './Identifiers';\nimport { comparePayloads } from './PayloadUtilities';\nimport { NodeData, Payload } from './persisted-types';\n\n/**\n * A node that can be contained within a Forest\n *\n * @public\n */\nexport interface ForestNode extends NodeData<NodeId> {\n\treadonly traits: ReadonlyMap<TraitLabel, readonly NodeId[]>;\n}\n\n/**\n * A node within a Forest that has a parent (and is therefore not the root node)\n *\n * @public\n */\nexport interface ParentedForestNode extends ForestNode, ParentData {}\n\n/**\n * Check whether or not the given node in a forest is parented\n *\n * @public\n */\nexport function isParentedForestNode(node: ForestNode): node is ParentedForestNode {\n\tconst parentedNode = node as ForestNode & Partial<ParentedForestNode>;\n\tconst hasParent = parentedNode.parentId !== undefined;\n\tconst hasTraitParent = parentedNode.traitParent !== undefined;\n\tassert(hasParent === hasTraitParent, 'node must have either both parent and traitParent set or neither');\n\treturn hasParent;\n}\n\n/**\n * Information about a ForestNode's parent\n *\n * @public\n */\nexport interface ParentData {\n\treadonly parentId: NodeId;\n\treadonly traitParent: TraitLabel;\n}\n\n/**\n * Differences from one forest to another.\n */\nexport interface Delta<NodeId> {\n\t/**\n\t * Nodes whose content changed.\n\t */\n\treadonly changed: readonly NodeId[];\n\t/**\n\t * Nodes that were added.\n\t */\n\treadonly added: readonly NodeId[];\n\t/**\n\t * Nodes that were removed.\n\t */\n\treadonly removed: readonly NodeId[];\n}\n\ninterface ForestState {\n\tnodes: BTree<NodeId, ForestNode>;\n\texpensiveValidation: boolean;\n}\n\n/**\n * An immutable forest of ForestNode.\n * Enforces single parenting, and allows querying the parent.\n *\n * @public\n */\nexport class Forest {\n\t/**\n\t * Contains the nodes in the forest.\n\t * Used as an immutable data-structure: must not be modified.\n\t */\n\tprivate readonly nodes: BTree<NodeId, ForestNode>;\n\n\t/**\n\t * If true, consistency checks will be applied after forest operations.\n\t */\n\tprivate readonly expensiveValidation: boolean;\n\n\t/**\n\t * Caller must ensure provided BTrees are not modified.\n\t * Will not modify the BTrees.\n\t */\n\tprivate constructor(data: ForestState);\n\n\t/**\n\t * Construct a new forest without reusing nodes from a previous one.\n\t */\n\tprivate constructor(expensiveValidation: boolean);\n\n\tprivate constructor(data?: ForestState | boolean) {\n\t\tif (typeof data === 'object') {\n\t\t\tthis.nodes = data.nodes;\n\t\t\tthis.expensiveValidation = data.expensiveValidation;\n\t\t} else {\n\t\t\tthis.nodes = new BTree<NodeId, ForestNode>(undefined, compareFiniteNumbers);\n\t\t\tthis.expensiveValidation = data ?? false;\n\t\t}\n\t\tif (this.expensiveValidation) {\n\t\t\tthis.assertConsistent();\n\t\t}\n\t}\n\n\t/**\n\t * Creates a new Forest.\n\t */\n\tpublic static create(expensiveValidation = false): Forest {\n\t\treturn new Forest(expensiveValidation);\n\t}\n\n\t/**\n\t * Returns the number of nodes in the forest.\n\t */\n\tpublic get size(): number {\n\t\treturn this.nodes.size;\n\t}\n\n\t/**\n\t * Adds the supplied nodes to the forest. The nodes' IDs must be unique in the forest.\n\t * @param nodes - the sequence of nodes to add to the forest. If any of them have children which exist in the forest already, those\n\t * children will be parented. Any trait arrays present in a node must be non-empty. The nodes may be provided in any order.\n\t */\n\tpublic add(nodes: Iterable<ForestNode>): Forest {\n\t\tconst newNodes = [...nodes];\n\t\tconst mutableNodes = this.nodes.clone();\n\n\t\t// This method iterates through the supplied nodes in two passes, first looking only at children and second actually adding the\n\t\t// nodes. This allows nodes to be passed in any order, e.g. a parent followed by a child or a child followed by a parent.\n\n\t\tconst childToParent = new Map<NodeId, ParentData>(); // Temporarily records the parentage of children that don't exist yet\n\n\t\t// First, inspect the children of each node. If the child is already in the forest, update its parentage. If it is not in the\n\t\t// forest, it may be about to be added in the second loop below so record its parentage temporarily for when that happens.\n\t\tfor (const node of newNodes) {\n\t\t\tconst { identifier } = node;\n\t\t\tfor (const [traitLabel, trait] of node.traits) {\n\t\t\t\tassert(trait.length > 0, 'any trait arrays present in a node must be non-empty');\n\t\t\t\tfor (const childId of trait) {\n\t\t\t\t\tconst child = mutableNodes.get(childId);\n\t\t\t\t\tif (child !== undefined) {\n\t\t\t\t\t\t// A child already exists in the forest, and its parent is now being added\n\t\t\t\t\t\tassert(!isParentedForestNode(child), 'can not give a child multiple parents');\n\t\t\t\t\t\tconst parentedChild = {\n\t\t\t\t\t\t\tdefinition: child.definition,\n\t\t\t\t\t\t\tidentifier: child.identifier,\n\t\t\t\t\t\t\ttraits: child.traits,\n\t\t\t\t\t\t\tparentId: identifier,\n\t\t\t\t\t\t\ttraitParent: traitLabel,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tcopyPropertyIfDefined(child, parentedChild, 'payload');\n\t\t\t\t\t\t// Overwrite the existing child with its parented version\n\t\t\t\t\t\tmutableNodes.set(childId, parentedChild);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// The child hasn't been added yet, so record its parentage to use when it is added below\n\t\t\t\t\t\tchildToParent.set(childId, { parentId: identifier, traitParent: traitLabel });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Now add each node to the forest and apply any parentage information that was recorded above\n\t\tfor (const node of newNodes) {\n\t\t\tconst parentData = childToParent.get(node.identifier);\n\t\t\tassert(!mutableNodes.has(node.identifier), 'can not add node with already existing id');\n\t\t\tif (parentData !== undefined) {\n\t\t\t\t// This is a child whom we haven't added yet, but whose parent we already added above. Supply the recorded parentage info.\n\t\t\t\tconst child = {\n\t\t\t\t\tdefinition: node.definition,\n\t\t\t\t\tidentifier: node.identifier,\n\t\t\t\t\ttraits: node.traits,\n\t\t\t\t\t...parentData,\n\t\t\t\t};\n\t\t\t\tcopyPropertyIfDefined(node, child, 'payload');\n\t\t\t\tmutableNodes.set(node.identifier, child);\n\t\t\t} else {\n\t\t\t\t// This is a node that has no parent. Add it with no parentage information.\n\t\t\t\tmutableNodes.set(node.identifier, node);\n\t\t\t}\n\t\t}\n\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\t/**\n\t * Parents a set of nodes already in the forest at a specified location within a trait.\n\t * @param parentId - the id of the parent under which to insert the new nodes\n\t * @param label - the label of the trait under which to insert the new nodes\n\t * @param index - the index in the trait after which to insert the new nodes\n\t * @param childIds - the ids of the nodes to insert\n\t */\n\tpublic attachRangeOfChildren(\n\t\tparentId: NodeId,\n\t\tlabel: TraitLabel,\n\t\tindex: number,\n\t\tchildIds: readonly NodeId[]\n\t): Forest {\n\t\tassert(index >= 0, 'invalid attach index');\n\t\tconst parentNode = this.nodes.get(parentId);\n\t\tassert(parentNode, 'can not insert children under node that does not exist');\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tconst traits = new Map(parentNode.traits);\n\t\tconst trait = traits.get(label) ?? [];\n\t\tassert(index <= trait.length, 'invalid attach index');\n\n\t\t// If there is nothing to insert, return early.\n\t\t// This is good for performance, but also avoids an edge case where an empty trait could be created (which is an error).\n\t\tif (childIds.length === 0) {\n\t\t\treturn this;\n\t\t}\n\t\tconst newChildren = [...trait.slice(0, index), ...childIds, ...trait.slice(index)];\n\t\ttraits.set(label, newChildren);\n\t\tmutableNodes.set(parentId, { ...parentNode, traits });\n\n\t\tfor (const childId of childIds) {\n\t\t\tmutableNodes.editRange(childId, childId, true, (_, n) => {\n\t\t\t\tassert(!isParentedForestNode(n), 'can not attach node that already has a parent');\n\t\t\t\tconst breakVal: { value: ParentedForestNode } = {\n\t\t\t\t\tvalue: {\n\t\t\t\t\t\t...n,\n\t\t\t\t\t\tparentId,\n\t\t\t\t\t\ttraitParent: label,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\treturn breakVal;\n\t\t\t});\n\t\t}\n\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\t/**\n\t * Detaches a range of nodes from their parent. The detached nodes remain in the `Forest`.\n\t * @param parentId - the id of the parent from which to detach the nodes\n\t * @param label - the label of the trait from which to detach the nodes\n\t * @param startIndex - the index of the first node in the range to detach\n\t * @param endIndex - the index after the last node in the range to detach\n\t * @returns a new `Forest` with the nodes detached, and a list of the ids of the nodes that were detached\n\t */\n\tpublic detachRangeOfChildren(\n\t\tparentId: NodeId,\n\t\tlabel: TraitLabel,\n\t\tstartIndex: number,\n\t\tendIndex: number\n\t): { forest: Forest; detached: readonly NodeId[] } {\n\t\tassert(startIndex >= 0 && endIndex >= startIndex, 'invalid detach index range');\n\t\tconst parentNode = this.nodes.get(parentId);\n\t\tassert(parentNode, 'can not detach children under node that does not exist');\n\t\tif (startIndex === endIndex) {\n\t\t\treturn { forest: this, detached: [] };\n\t\t}\n\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tconst traits = new Map(parentNode.traits);\n\t\tconst trait = traits.get(label) ?? [];\n\t\tassert(endIndex <= trait.length, 'invalid detach index range');\n\t\tconst detached: NodeId[] = trait.slice(startIndex, endIndex);\n\t\tconst newChildren = [...trait.slice(0, startIndex), ...trait.slice(endIndex)];\n\t\tconst deleteTrait = newChildren.length === 0;\n\t\tif (deleteTrait) {\n\t\t\ttraits.delete(label);\n\t\t} else {\n\t\t\ttraits.set(label, newChildren);\n\t\t}\n\n\t\tmutableNodes.set(parentId, { ...parentNode, traits });\n\t\tfor (const childId of detached) {\n\t\t\tmutableNodes.editRange(childId, childId, true, (_, n) => {\n\t\t\t\tconst breakVal: { value: ForestNode } = {\n\t\t\t\t\tvalue: {\n\t\t\t\t\t\tdefinition: n.definition,\n\t\t\t\t\t\tidentifier: n.identifier,\n\t\t\t\t\t\ttraits: n.traits,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tcopyPropertyIfDefined(n, breakVal.value, 'payload');\n\t\t\t\treturn breakVal;\n\t\t\t});\n\t\t}\n\n\t\treturn {\n\t\t\tforest: new Forest({\n\t\t\t\tnodes: mutableNodes,\n\t\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t\t}),\n\t\t\tdetached,\n\t\t};\n\t}\n\n\t/**\n\t * Replaces a node's value. The node must exist in this `Forest`.\n\t * @param nodeId - the id of the node\n\t * @param value - the new value\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tpublic setValue(nodeId: NodeId, value: Payload | null): Forest {\n\t\tconst node = this.nodes.get(nodeId);\n\t\tassert(node, 'can not replace payload for node that does not exist');\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tconst newNode = { ...node };\n\t\tif (value !== null) {\n\t\t\tnewNode.payload = value;\n\t\t} else {\n\t\t\tdelete newNode.payload;\n\t\t}\n\t\tmutableNodes.set(nodeId, newNode);\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\t/**\n\t * @returns true if the node associated with `id` exists in this forest, otherwise false\n\t */\n\tpublic has(id: NodeId): boolean {\n\t\treturn this.nodes.has(id);\n\t}\n\n\t/**\n\t * @returns the node associated with `id`. Should not be used if there is no node with the provided id.\n\t */\n\tpublic get(id: NodeId): ForestNode {\n\t\treturn this.nodes.get(id) ?? fail('NodeId not found');\n\t}\n\n\t/**\n\t * @returns the node associated with `id`, or undefined if there is none\n\t */\n\tpublic tryGet(id: NodeId): ForestNode | undefined {\n\t\treturn this.nodes.get(id);\n\t}\n\n\t/**\n\t * Deletes every node in ids (each of which must be unparented)\n\t * @param ids - The IDs of the nodes to delete.\n\t * @param deleteChildren - If true, recursively deletes descendants. Otherwise, leaves children unparented.\n\t */\n\tpublic delete(ids: Iterable<NodeId>, deleteChildren: boolean): Forest {\n\t\tconst mutableNodes = this.nodes.clone();\n\t\tfor (const id of ids) {\n\t\t\tthis.deleteRecursive(mutableNodes, id, deleteChildren);\n\t\t}\n\n\t\treturn new Forest({\n\t\t\tnodes: mutableNodes,\n\t\t\texpensiveValidation: this.expensiveValidation,\n\t\t});\n\t}\n\n\tprivate deleteRecursive(mutableNodes: BTree<NodeId, ForestNode>, id: NodeId, deleteChildren: boolean): void {\n\t\tconst node = mutableNodes.get(id) ?? fail('node to delete must exist');\n\t\tassert(!isParentedForestNode(node), 'deleted nodes must be unparented');\n\t\tmutableNodes.delete(id);\n\t\tfor (const trait of node.traits.values()) {\n\t\t\tfor (const childId of trait) {\n\t\t\t\tmutableNodes.editRange(childId, childId, true, (_, n) => {\n\t\t\t\t\tconst breakVal: { value: ForestNode } = {\n\t\t\t\t\t\tvalue: {\n\t\t\t\t\t\t\tdefinition: n.definition,\n\t\t\t\t\t\t\tidentifier: n.identifier,\n\t\t\t\t\t\t\ttraits: n.traits,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tcopyPropertyIfDefined(n, breakVal.value, 'payload');\n\t\t\t\t\treturn breakVal;\n\t\t\t\t});\n\n\t\t\t\tif (deleteChildren) {\n\t\t\t\t\tthis.deleteRecursive(mutableNodes, childId, deleteChildren);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks that the metadata is correct, and the items form a forest.\n\t * This is an expensive O(map size) operation.\n\t */\n\tpublic assertConsistent(): void {\n\t\tconst checkedChildren = new Set<NodeId>([]);\n\t\tfor (const [nodeId, node] of this.nodes.entries(undefined, [])) {\n\t\t\tif (isParentedForestNode(node)) {\n\t\t\t\tconst parent = this.get(node.parentId);\n\t\t\t\tconst trait = parent.traits.get(node.traitParent);\n\t\t\t\tassert(trait !== undefined);\n\t\t\t\tassert(trait.includes(node.identifier), 'node is parented incorrectly');\n\t\t\t}\n\n\t\t\tfor (const trait of node.traits.values()) {\n\t\t\t\tassert(trait.length > 0, 'trait is present but empty');\n\t\t\t\tfor (const childId of trait) {\n\t\t\t\t\tconst child = this.nodes.get(childId);\n\t\t\t\t\tassert(child, 'child in trait is not in forest');\n\t\t\t\t\tassert(isParentedForestNode(child), 'child is not parented');\n\t\t\t\t\tassert(child.parentId === node.identifier, 'child parent pointer is incorrect');\n\t\t\t\t\tassert(\n\t\t\t\t\t\t!checkedChildren.has(childId),\n\t\t\t\t\t\t'the item tree tree must not contain cycles or multi-parented nodes'\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\t(child.parentId ?? fail('each node must have associated metadata')) === nodeId,\n\t\t\t\t\t\t'cached parent is incorrect'\n\t\t\t\t\t);\n\t\t\t\t\tcheckedChildren.add(childId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @returns the parent of `id`. Should not be used if there is no node with id or if id refers to the root node.\n\t */\n\tpublic getParent(id: NodeId): ParentData {\n\t\tconst child = this.nodes.get(id);\n\t\tif (child === undefined) {\n\t\t\tfail('NodeId not found');\n\t\t}\n\n\t\tassert(isParentedForestNode(child), 'Node is not parented');\n\t\treturn { parentId: child.parentId, traitParent: child.traitParent };\n\t}\n\n\t/**\n\t * @returns undefined iff root, otherwise the parent of `id`.\n\t */\n\tpublic tryGetParent(id: NodeId): ParentData | undefined {\n\t\tconst child = this.nodes.get(id);\n\t\tif (child === undefined || !isParentedForestNode(child)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tparentId: child.parentId,\n\t\t\ttraitParent: child.traitParent,\n\t\t};\n\t}\n\n\t/**\n\t * Compares two forests for equality.\n\t * @param forest - the other forest to compare to this one\n\t * @param comparator - a function which returns true if two objects of type ForestNode are equivalent, false otherwise\n\t * @returns true iff the forests are equal.\n\t */\n\tpublic equals(forest: Forest): boolean {\n\t\tif (this === forest || this.nodes === forest.nodes) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (forest.size !== this.size) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn compareBtrees(this.nodes, forest.nodes, compareForestNodes);\n\t}\n\n\t/**\n\t * Calculate the difference between two forests.\n\t * @param forest - the other forest to compare to this one\n\t * @param comparator - a function which returns true if two objects of type ForestNode are equivalent, false otherwise\n\t * @returns A {@link Delta} listing which nodes must be changed, added, and removed to get from `this` to `forest`.\n\t */\n\tpublic delta(forest: Forest): Delta<NodeId> {\n\t\tconst changed: NodeId[] = [];\n\t\tconst removed: NodeId[] = [];\n\t\tconst added: NodeId[] = [];\n\t\tthis.nodes.diffAgainst(\n\t\t\tforest.nodes,\n\t\t\t(id) => {\n\t\t\t\tremoved.push(id);\n\t\t\t},\n\t\t\t(id) => {\n\t\t\t\tadded.push(id);\n\t\t\t},\n\t\t\t(id, nodeThis, nodeOther) => {\n\t\t\t\tif (!compareForestNodes(nodeThis, nodeOther)) {\n\t\t\t\t\tchanged.push(id);\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t\treturn {\n\t\t\tchanged,\n\t\t\tadded,\n\t\t\tremoved,\n\t\t};\n\t}\n}\n\n/**\n * @returns true iff two `ForestNodes` are equivalent.\n * May return false for nodes they contain equivalent payloads encoded differently.\n */\nexport function compareForestNodes(nodeA: ForestNode, nodeB: ForestNode): boolean {\n\tif (nodeA === nodeB) {\n\t\treturn true;\n\t}\n\n\tif (nodeA.identifier !== nodeB.identifier) {\n\t\treturn false;\n\t}\n\n\tif (nodeA.definition !== nodeB.definition) {\n\t\treturn false;\n\t}\n\n\tif (!comparePayloads(nodeA.payload, nodeB.payload)) {\n\t\treturn false;\n\t}\n\n\tif (nodeA.traits.size !== nodeB.traits.size) {\n\t\treturn false;\n\t}\n\n\tfor (const traitA of nodeA.traits) {\n\t\tconst [traitLabelA, nodeSequenceA] = traitA;\n\t\tconst nodeSequenceB = nodeB.traits.get(traitLabelA);\n\t\tif (!nodeSequenceB) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (nodeSequenceA.length !== nodeSequenceB.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (let i = 0; i < nodeSequenceA.length; i++) {\n\t\t\tif (nodeSequenceA[i] !== nodeSequenceB[i]) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n}\n"]}
|