@fluidframework/tree 2.13.0 → 2.20.0
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/CHANGELOG.md +18 -0
- package/api-report/tree.alpha.api.md +22 -12
- package/api-report/tree.beta.api.md +9 -5
- package/api-report/tree.legacy.alpha.api.md +9 -5
- package/api-report/tree.legacy.public.api.md +9 -5
- package/api-report/tree.public.api.md +9 -5
- package/assertTagging.config.mjs +14 -0
- package/dist/alpha.d.ts +3 -0
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +6 -4
- package/dist/core/index.js.map +1 -1
- package/dist/core/rebase/index.d.ts +2 -2
- package/dist/core/rebase/index.d.ts.map +1 -1
- package/dist/core/rebase/index.js +5 -1
- package/dist/core/rebase/index.js.map +1 -1
- package/dist/core/rebase/types.d.ts +5 -4
- package/dist/core/rebase/types.d.ts.map +1 -1
- package/dist/core/rebase/types.js +29 -1
- package/dist/core/rebase/types.js.map +1 -1
- package/dist/core/rebase/utils.d.ts +10 -0
- package/dist/core/rebase/utils.d.ts.map +1 -1
- package/dist/core/rebase/utils.js +22 -1
- package/dist/core/rebase/utils.js.map +1 -1
- package/dist/core/tree/delta.d.ts +21 -26
- package/dist/core/tree/delta.d.ts.map +1 -1
- package/dist/core/tree/delta.js.map +1 -1
- package/dist/core/tree/deltaUtil.d.ts +1 -3
- package/dist/core/tree/deltaUtil.d.ts.map +1 -1
- package/dist/core/tree/deltaUtil.js +2 -14
- package/dist/core/tree/deltaUtil.js.map +1 -1
- package/dist/core/tree/index.d.ts +1 -1
- package/dist/core/tree/index.d.ts.map +1 -1
- package/dist/core/tree/index.js +1 -3
- package/dist/core/tree/index.js.map +1 -1
- package/dist/core/tree/visitDelta.d.ts.map +1 -1
- package/dist/core/tree/visitDelta.js +82 -80
- package/dist/core/tree/visitDelta.js.map +1 -1
- package/dist/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
- package/dist/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
- package/dist/feature-libraries/deltaUtils.d.ts.map +1 -1
- package/dist/feature-libraries/deltaUtils.js +13 -0
- package/dist/feature-libraries/deltaUtils.js.map +1 -1
- package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
- package/dist/feature-libraries/forest-summary/forestSummarizer.js +1 -6
- package/dist/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
- package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts +5 -5
- package/dist/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/crossFieldQueries.js +2 -9
- package/dist/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
- package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts +19 -2
- package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/fieldChangeHandler.js.map +1 -1
- package/dist/feature-libraries/modular-schema/genericFieldKind.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
- package/dist/feature-libraries/modular-schema/index.d.ts +2 -2
- package/dist/feature-libraries/modular-schema/index.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/index.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.d.ts +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.js +8 -8
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts +4 -4
- package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js +105 -199
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts +11 -20
- package/dist/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeTypes.js +20 -0
- package/dist/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
- package/dist/feature-libraries/optional-field/optionalField.d.ts +3 -3
- package/dist/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
- package/dist/feature-libraries/optional-field/optionalField.js.map +1 -1
- package/dist/feature-libraries/sequence-field/moveEffectTable.d.ts +1 -1
- package/dist/feature-libraries/sequence-field/moveEffectTable.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/moveEffectTable.js.map +1 -1
- package/dist/feature-libraries/sequence-field/rebase.js +4 -4
- package/dist/feature-libraries/sequence-field/rebase.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV1.js +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV1.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.js +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldCodecV2.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts +2 -3
- package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldToDelta.js.map +1 -1
- package/dist/feature-libraries/sequence-field/utils.js +36 -4
- package/dist/feature-libraries/sequence-field/utils.js.map +1 -1
- package/dist/feature-libraries/treeCursorUtils.d.ts.map +1 -1
- package/dist/feature-libraries/treeCursorUtils.js +4 -1
- package/dist/feature-libraries/treeCursorUtils.js.map +1 -1
- package/dist/index.d.ts +26 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/package.json +2 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/shared-tree/index.d.ts +1 -1
- package/dist/shared-tree/index.d.ts.map +1 -1
- package/dist/shared-tree/index.js +4 -2
- package/dist/shared-tree/index.js.map +1 -1
- package/dist/shared-tree/sharedTree.d.ts +38 -18
- package/dist/shared-tree/sharedTree.d.ts.map +1 -1
- package/dist/shared-tree/sharedTree.js +38 -34
- package/dist/shared-tree/sharedTree.js.map +1 -1
- package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
- package/dist/shared-tree/treeCheckout.js +12 -8
- package/dist/shared-tree/treeCheckout.js.map +1 -1
- package/dist/simple-tree/api/treeNodeApi.js +1 -1
- package/dist/simple-tree/api/treeNodeApi.js.map +1 -1
- package/dist/simple-tree/arrayNode.js +1 -1
- package/dist/simple-tree/arrayNode.js.map +1 -1
- package/dist/simple-tree/toMapTree.js +1 -1
- package/dist/simple-tree/toMapTree.js.map +1 -1
- package/dist/util/bTreeUtils.d.ts +10 -0
- package/dist/util/bTreeUtils.d.ts.map +1 -0
- package/dist/util/bTreeUtils.js +52 -0
- package/dist/util/bTreeUtils.js.map +1 -0
- package/dist/util/idAllocator.d.ts +0 -2
- package/dist/util/idAllocator.d.ts.map +1 -1
- package/dist/util/idAllocator.js +0 -2
- package/dist/util/idAllocator.js.map +1 -1
- package/dist/util/index.d.ts +2 -1
- package/dist/util/index.d.ts.map +1 -1
- package/dist/util/index.js +5 -1
- package/dist/util/index.js.map +1 -1
- package/dist/util/rangeMap.d.ts +52 -30
- package/dist/util/rangeMap.d.ts.map +1 -1
- package/dist/util/rangeMap.js +161 -117
- package/dist/util/rangeMap.js.map +1 -1
- package/dist/util/utils.d.ts +4 -1
- package/dist/util/utils.d.ts.map +1 -1
- package/dist/util/utils.js +7 -1
- package/dist/util/utils.js.map +1 -1
- package/lib/alpha.d.ts +3 -0
- package/lib/core/index.d.ts +2 -2
- package/lib/core/index.d.ts.map +1 -1
- package/lib/core/index.js +2 -2
- package/lib/core/index.js.map +1 -1
- package/lib/core/rebase/index.d.ts +2 -2
- package/lib/core/rebase/index.d.ts.map +1 -1
- package/lib/core/rebase/index.js +2 -2
- package/lib/core/rebase/index.js.map +1 -1
- package/lib/core/rebase/types.d.ts +5 -4
- package/lib/core/rebase/types.d.ts.map +1 -1
- package/lib/core/rebase/types.js +26 -1
- package/lib/core/rebase/types.js.map +1 -1
- package/lib/core/rebase/utils.d.ts +10 -0
- package/lib/core/rebase/utils.d.ts.map +1 -1
- package/lib/core/rebase/utils.js +20 -0
- package/lib/core/rebase/utils.js.map +1 -1
- package/lib/core/tree/delta.d.ts +21 -26
- package/lib/core/tree/delta.d.ts.map +1 -1
- package/lib/core/tree/delta.js.map +1 -1
- package/lib/core/tree/deltaUtil.d.ts +1 -3
- package/lib/core/tree/deltaUtil.d.ts.map +1 -1
- package/lib/core/tree/deltaUtil.js +1 -12
- package/lib/core/tree/deltaUtil.js.map +1 -1
- package/lib/core/tree/index.d.ts +1 -1
- package/lib/core/tree/index.d.ts.map +1 -1
- package/lib/core/tree/index.js +1 -1
- package/lib/core/tree/index.js.map +1 -1
- package/lib/core/tree/visitDelta.d.ts.map +1 -1
- package/lib/core/tree/visitDelta.js +82 -80
- package/lib/core/tree/visitDelta.js.map +1 -1
- package/lib/feature-libraries/default-schema/defaultFieldKinds.d.ts.map +1 -1
- package/lib/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
- package/lib/feature-libraries/deltaUtils.d.ts.map +1 -1
- package/lib/feature-libraries/deltaUtils.js +13 -0
- package/lib/feature-libraries/deltaUtils.js.map +1 -1
- package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
- package/lib/feature-libraries/forest-summary/forestSummarizer.js +1 -6
- package/lib/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
- package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts +5 -5
- package/lib/feature-libraries/modular-schema/crossFieldQueries.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/crossFieldQueries.js +2 -9
- package/lib/feature-libraries/modular-schema/crossFieldQueries.js.map +1 -1
- package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts +19 -2
- package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/fieldChangeHandler.js.map +1 -1
- package/lib/feature-libraries/modular-schema/genericFieldKind.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
- package/lib/feature-libraries/modular-schema/index.d.ts +2 -2
- package/lib/feature-libraries/modular-schema/index.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/index.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.d.ts +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.js +4 -4
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts +4 -4
- package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js +74 -166
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts +11 -20
- package/lib/feature-libraries/modular-schema/modularChangeTypes.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeTypes.js +18 -1
- package/lib/feature-libraries/modular-schema/modularChangeTypes.js.map +1 -1
- package/lib/feature-libraries/optional-field/optionalField.d.ts +3 -3
- package/lib/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
- package/lib/feature-libraries/optional-field/optionalField.js.map +1 -1
- package/lib/feature-libraries/sequence-field/moveEffectTable.d.ts +1 -1
- package/lib/feature-libraries/sequence-field/moveEffectTable.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/moveEffectTable.js.map +1 -1
- package/lib/feature-libraries/sequence-field/rebase.js +4 -4
- package/lib/feature-libraries/sequence-field/rebase.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV1.js +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV1.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.js +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldCodecV2.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts +2 -3
- package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldToDelta.js.map +1 -1
- package/lib/feature-libraries/sequence-field/utils.js +36 -4
- package/lib/feature-libraries/sequence-field/utils.js.map +1 -1
- package/lib/feature-libraries/treeCursorUtils.d.ts.map +1 -1
- package/lib/feature-libraries/treeCursorUtils.js +4 -1
- package/lib/feature-libraries/treeCursorUtils.js.map +1 -1
- package/lib/index.d.ts +26 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/shared-tree/index.d.ts +1 -1
- package/lib/shared-tree/index.d.ts.map +1 -1
- package/lib/shared-tree/index.js +1 -1
- package/lib/shared-tree/index.js.map +1 -1
- package/lib/shared-tree/sharedTree.d.ts +38 -18
- package/lib/shared-tree/sharedTree.d.ts.map +1 -1
- package/lib/shared-tree/sharedTree.js +37 -33
- package/lib/shared-tree/sharedTree.js.map +1 -1
- package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
- package/lib/shared-tree/treeCheckout.js +13 -9
- package/lib/shared-tree/treeCheckout.js.map +1 -1
- package/lib/simple-tree/api/treeNodeApi.js +1 -1
- package/lib/simple-tree/api/treeNodeApi.js.map +1 -1
- package/lib/simple-tree/arrayNode.js +1 -1
- package/lib/simple-tree/arrayNode.js.map +1 -1
- package/lib/simple-tree/toMapTree.js +1 -1
- package/lib/simple-tree/toMapTree.js.map +1 -1
- package/lib/util/bTreeUtils.d.ts +10 -0
- package/lib/util/bTreeUtils.d.ts.map +1 -0
- package/lib/util/bTreeUtils.js +47 -0
- package/lib/util/bTreeUtils.js.map +1 -0
- package/lib/util/idAllocator.d.ts +0 -2
- package/lib/util/idAllocator.d.ts.map +1 -1
- package/lib/util/idAllocator.js +0 -2
- package/lib/util/idAllocator.js.map +1 -1
- package/lib/util/index.d.ts +2 -1
- package/lib/util/index.d.ts.map +1 -1
- package/lib/util/index.js +2 -1
- package/lib/util/index.js.map +1 -1
- package/lib/util/rangeMap.d.ts +52 -30
- package/lib/util/rangeMap.d.ts.map +1 -1
- package/lib/util/rangeMap.js +160 -117
- package/lib/util/rangeMap.js.map +1 -1
- package/lib/util/utils.d.ts +4 -1
- package/lib/util/utils.d.ts.map +1 -1
- package/lib/util/utils.js +7 -1
- package/lib/util/utils.js.map +1 -1
- package/package.json +23 -23
- package/src/core/index.ts +5 -2
- package/src/core/rebase/index.ts +5 -0
- package/src/core/rebase/types.ts +33 -5
- package/src/core/rebase/utils.ts +27 -0
- package/src/core/tree/delta.ts +21 -26
- package/src/core/tree/deltaUtil.ts +1 -16
- package/src/core/tree/index.ts +0 -2
- package/src/core/tree/visitDelta.ts +108 -97
- package/src/feature-libraries/default-schema/defaultFieldKinds.ts +2 -2
- package/src/feature-libraries/deltaUtils.ts +13 -0
- package/src/feature-libraries/forest-summary/forestSummarizer.ts +1 -6
- package/src/feature-libraries/modular-schema/crossFieldQueries.ts +12 -13
- package/src/feature-libraries/modular-schema/fieldChangeHandler.ts +21 -1
- package/src/feature-libraries/modular-schema/genericFieldKind.ts +2 -2
- package/src/feature-libraries/modular-schema/index.ts +2 -0
- package/src/feature-libraries/modular-schema/modularChangeCodecs.ts +12 -11
- package/src/feature-libraries/modular-schema/modularChangeFamily.ts +138 -225
- package/src/feature-libraries/modular-schema/modularChangeTypes.ts +40 -27
- package/src/feature-libraries/optional-field/optionalField.ts +3 -3
- package/src/feature-libraries/sequence-field/moveEffectTable.ts +1 -1
- package/src/feature-libraries/sequence-field/rebase.ts +9 -3
- package/src/feature-libraries/sequence-field/sequenceFieldCodecV1.ts +1 -1
- package/src/feature-libraries/sequence-field/sequenceFieldCodecV2.ts +1 -1
- package/src/feature-libraries/sequence-field/sequenceFieldToDelta.ts +3 -4
- package/src/feature-libraries/sequence-field/utils.ts +36 -4
- package/src/feature-libraries/treeCursorUtils.ts +6 -1
- package/src/index.ts +34 -6
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/index.ts +4 -1
- package/src/shared-tree/sharedTree.ts +60 -40
- package/src/shared-tree/treeCheckout.ts +19 -12
- package/src/simple-tree/api/treeNodeApi.ts +1 -1
- package/src/simple-tree/arrayNode.ts +1 -1
- package/src/simple-tree/toMapTree.ts +1 -1
- package/src/util/bTreeUtils.ts +60 -0
- package/src/util/idAllocator.ts +0 -2
- package/src/util/index.ts +3 -0
- package/src/util/rangeMap.ts +208 -143
- package/src/util/utils.ts +10 -3
- package/lib/package.json +0 -3
package/src/util/rangeMap.ts
CHANGED
|
@@ -3,25 +3,80 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { oob } from "@fluidframework/core-utils/internal";
|
|
6
|
+
import { assert, oob } from "@fluidframework/core-utils/internal";
|
|
7
|
+
import { BTree } from "@tylerbu/sorted-btree-es6";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
|
-
* RangeMap represents a mapping from
|
|
10
|
+
* RangeMap represents a mapping from keys of type K to values of type V or undefined.
|
|
11
|
+
* The set of all possible keys is assumed to be fully ordered,
|
|
12
|
+
* and for each key there should be a single next higher key.
|
|
10
13
|
* The values for a range of consecutive keys can be changed or queried in a single operation.
|
|
14
|
+
* The structure of the keys is described by the `offsetKey` and `subtractKeys` functions provided in the constructor.
|
|
11
15
|
*/
|
|
12
|
-
export class RangeMap<
|
|
13
|
-
private
|
|
16
|
+
export class RangeMap<K, V> {
|
|
17
|
+
private tree: BTree<K, RangeEntry<V>>;
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
/**
|
|
20
|
+
* @param offsetKey - Function which returns a new key which is `offset` keys after `key`.
|
|
21
|
+
* When `offset` is negative, the returned key should come before `key`.
|
|
22
|
+
*
|
|
23
|
+
* @param subtractKeys - Function which returns the difference between `b` and `a`.
|
|
24
|
+
* Offsetting `b` by this difference should return `a`.
|
|
25
|
+
* The difference can be infinite if `a` cannot be reached from `b` by offsetting,
|
|
26
|
+
* but the difference should still be positive if `a` is larger than `b` and negative if smaller.
|
|
27
|
+
*/
|
|
28
|
+
public constructor(
|
|
29
|
+
private readonly offsetKey: (key: K, offset: number) => K,
|
|
30
|
+
private readonly subtractKeys: (a: K, b: K) => number,
|
|
31
|
+
) {
|
|
32
|
+
this.tree = new BTree(undefined, subtractKeys);
|
|
17
33
|
}
|
|
18
34
|
|
|
19
35
|
/**
|
|
20
|
-
* Retrieves all entries from the
|
|
21
|
-
* @returns An array of RangeEntryResult objects, each containing the start index, length, and value of a contiguous range.
|
|
36
|
+
* Retrieves all entries from the RangeMap.
|
|
22
37
|
*/
|
|
23
|
-
public
|
|
24
|
-
|
|
38
|
+
public entries(): RangeQueryEntry<K, V>[] {
|
|
39
|
+
const entries: RangeQueryEntry<K, V>[] = [];
|
|
40
|
+
for (const [start, entry] of this.tree.entries()) {
|
|
41
|
+
entries.push({ start, length: entry.length, value: entry.value });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return entries;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public clear(): void {
|
|
48
|
+
this.tree.clear();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Retrieves the values for all keys in the query range.
|
|
53
|
+
*
|
|
54
|
+
* @param start - The first key in the range being queried
|
|
55
|
+
* @param length - The length of the query range
|
|
56
|
+
* @returns A list of entries, each describing the value for some subrange of the query.
|
|
57
|
+
* The entries are in the same order as the keys, and there is an entry for every key with a non `undefined` value.
|
|
58
|
+
*/
|
|
59
|
+
public getAll(start: K, length: number): RangeQueryEntry<K, V>[] {
|
|
60
|
+
const entries = this.getIntersectingEntries(start, length);
|
|
61
|
+
if (entries.length === 0) {
|
|
62
|
+
return entries;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const firstEntry = entries[0] ?? oob();
|
|
66
|
+
const lengthBefore = this.subtractKeys(start, firstEntry.start);
|
|
67
|
+
if (lengthBefore > 0) {
|
|
68
|
+
entries[0] = { ...firstEntry, start, length: firstEntry.length - lengthBefore };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const lastEntry = entries[entries.length - 1] ?? oob();
|
|
72
|
+
const lastEntryKey = this.offsetKey(lastEntry.start, lastEntry.length - 1);
|
|
73
|
+
const lastQueryKey = this.offsetKey(start, length - 1);
|
|
74
|
+
const lengthAfter = this.subtractKeys(lastEntryKey, lastQueryKey);
|
|
75
|
+
if (lengthAfter > 0) {
|
|
76
|
+
entries[entries.length - 1] = { ...lastEntry, length: lastEntry.length - lengthAfter };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return entries;
|
|
25
80
|
}
|
|
26
81
|
|
|
27
82
|
/**
|
|
@@ -30,23 +85,39 @@ export class RangeMap<T> {
|
|
|
30
85
|
* @param start - The first key in the query range.
|
|
31
86
|
* @param length - The length of the query range.
|
|
32
87
|
* @returns A RangeQueryResult containing the value associated with `start`,
|
|
33
|
-
* and the number of consecutive keys with that same value.
|
|
88
|
+
* and the number of consecutive keys with that same value (at least 1, at most `length`).
|
|
34
89
|
*/
|
|
35
|
-
public
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
90
|
+
public getFirst(start: K, length: number): RangeQueryResult<K, V> {
|
|
91
|
+
{
|
|
92
|
+
// We first check for an entry with a key less than or equal to `start`.
|
|
93
|
+
const entry = this.tree.getPairOrNextLower(start);
|
|
94
|
+
if (entry !== undefined) {
|
|
95
|
+
const entryKey = entry[0];
|
|
96
|
+
const { value, length: entryLength } = entry[1];
|
|
40
97
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
98
|
+
const entryLastKey = this.offsetKey(entryKey, entryLength - 1);
|
|
99
|
+
const overlappingLength = Math.min(this.subtractKeys(entryLastKey, start) + 1, length);
|
|
100
|
+
if (overlappingLength > 0) {
|
|
101
|
+
return { value, start, length: overlappingLength };
|
|
102
|
+
}
|
|
45
103
|
}
|
|
46
104
|
}
|
|
47
105
|
|
|
48
|
-
|
|
49
|
-
|
|
106
|
+
{
|
|
107
|
+
// There is no value associated with `start`.
|
|
108
|
+
// Now we need to determine how many of the following keys are also undefined.
|
|
109
|
+
const key = this.tree.nextHigherKey(start);
|
|
110
|
+
if (key !== undefined) {
|
|
111
|
+
const entryKey = key;
|
|
112
|
+
|
|
113
|
+
const lastQueryKey = this.offsetKey(start, length - 1);
|
|
114
|
+
if (this.le(entryKey, lastQueryKey)) {
|
|
115
|
+
return { value: undefined, start, length: this.subtractKeys(entryKey, start) };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return { value: undefined, start, length };
|
|
120
|
+
}
|
|
50
121
|
}
|
|
51
122
|
|
|
52
123
|
/**
|
|
@@ -56,74 +127,11 @@ export class RangeMap<T> {
|
|
|
56
127
|
* @param length - The length of the range.
|
|
57
128
|
* @param value - The value to associate with the range.
|
|
58
129
|
*/
|
|
59
|
-
public set(start:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
130
|
+
public set(start: K, length: number, value: V | undefined): void {
|
|
131
|
+
this.delete(start, length);
|
|
132
|
+
if (value !== undefined) {
|
|
133
|
+
this.tree.set(start, { value, length });
|
|
63
134
|
}
|
|
64
|
-
|
|
65
|
-
const end = start + length - 1;
|
|
66
|
-
const newEntry: RangeEntry<T> = { start, length, value };
|
|
67
|
-
|
|
68
|
-
let iBefore = -1;
|
|
69
|
-
let iAfter = this.entries.length;
|
|
70
|
-
for (const [i, entry] of this.entries.entries()) {
|
|
71
|
-
const entryLastKey = entry.start + entry.length - 1;
|
|
72
|
-
if (entryLastKey < start) {
|
|
73
|
-
iBefore = i;
|
|
74
|
-
} else if (entry.start > end) {
|
|
75
|
-
iAfter = i;
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const numOverlappingEntries = iAfter - iBefore - 1;
|
|
81
|
-
if (numOverlappingEntries === 0) {
|
|
82
|
-
this.entries.splice(iAfter, 0, newEntry);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const iFirst = iBefore + 1;
|
|
87
|
-
const firstEntry = this.entries[iFirst] ?? oob();
|
|
88
|
-
const iLast = iAfter - 1;
|
|
89
|
-
const lastEntry = this.entries[iLast] ?? oob();
|
|
90
|
-
const lengthBeforeFirst = start - firstEntry.start;
|
|
91
|
-
const lastEntryKey = lastEntry.start + lastEntry.length - 1;
|
|
92
|
-
const lengthAfterLast = lastEntryKey - end;
|
|
93
|
-
|
|
94
|
-
if (lengthBeforeFirst > 0 && lengthAfterLast > 0 && iFirst === iLast) {
|
|
95
|
-
// The new entry fits in the middle of an existing entry.
|
|
96
|
-
// We replace the existing entry with:
|
|
97
|
-
// 1) the portion which comes before `newEntry`
|
|
98
|
-
// 2) `newEntry`
|
|
99
|
-
// 3) the portion which comes after `newEntry`
|
|
100
|
-
this.entries.splice(iFirst, 1, { ...firstEntry, length: lengthBeforeFirst }, newEntry, {
|
|
101
|
-
...lastEntry,
|
|
102
|
-
start: end + 1,
|
|
103
|
-
length: lengthAfterLast,
|
|
104
|
-
});
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if (lengthBeforeFirst > 0) {
|
|
109
|
-
this.entries[iFirst] = { ...firstEntry, length: lengthBeforeFirst };
|
|
110
|
-
// The entry at `iFirst` is no longer overlapping with `newEntry`.
|
|
111
|
-
iBefore = iFirst;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (lengthAfterLast > 0) {
|
|
115
|
-
this.entries[iLast] = {
|
|
116
|
-
...lastEntry,
|
|
117
|
-
start: end + 1,
|
|
118
|
-
length: lengthAfterLast,
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
// The entry at `iLast` is no longer overlapping with `newEntry`.
|
|
122
|
-
iAfter = iLast;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const numContainedEntries = iAfter - iBefore - 1;
|
|
126
|
-
this.entries.splice(iBefore + 1, numContainedEntries, newEntry);
|
|
127
135
|
}
|
|
128
136
|
|
|
129
137
|
/**
|
|
@@ -146,74 +154,110 @@ export class RangeMap<T> {
|
|
|
146
154
|
* @param start - The start of the range to delete (inclusive).
|
|
147
155
|
* @param length - The length of the range to delete.
|
|
148
156
|
*/
|
|
149
|
-
public delete(start:
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const
|
|
157
|
-
if (
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
157
|
+
public delete(start: K, length: number): void {
|
|
158
|
+
const lastDeleteKey = this.offsetKey(start, length - 1);
|
|
159
|
+
for (const { start: key, length: entryLength, value } of this.getIntersectingEntries(
|
|
160
|
+
start,
|
|
161
|
+
length,
|
|
162
|
+
)) {
|
|
163
|
+
this.tree.delete(key);
|
|
164
|
+
const lengthBefore = this.subtractKeys(start, key);
|
|
165
|
+
if (lengthBefore > 0) {
|
|
166
|
+
// A portion of this entry comes before the deletion range, so we reinsert that portion.
|
|
167
|
+
this.tree.set(key, { length: lengthBefore, value });
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const lastEntryKey = this.offsetKey(key, entryLength - 1);
|
|
171
|
+
const lengthAfter = this.subtractKeys(lastEntryKey, lastDeleteKey);
|
|
172
|
+
if (lengthAfter > 0) {
|
|
173
|
+
// A portion of this entry comes after the deletion range, so we reinsert that portion.
|
|
174
|
+
this.tree.set(this.offsetKey(lastDeleteKey, 1), { length: lengthAfter, value });
|
|
162
175
|
}
|
|
163
176
|
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
public clone(): RangeMap<K, V> {
|
|
180
|
+
const cloned = new RangeMap<K, V>(this.offsetKey, this.subtractKeys);
|
|
181
|
+
cloned.tree = this.tree.clone();
|
|
182
|
+
return cloned;
|
|
183
|
+
}
|
|
164
184
|
|
|
165
|
-
|
|
185
|
+
/**
|
|
186
|
+
* Returns a new map which contains the entries from both input maps.
|
|
187
|
+
*/
|
|
188
|
+
public static union<K, V>(a: RangeMap<K, V>, b: RangeMap<K, V>): RangeMap<K, V> {
|
|
189
|
+
assert(
|
|
190
|
+
a.offsetKey === b.offsetKey && a.subtractKeys === b.subtractKeys,
|
|
191
|
+
0xaae /* Maps should have the same behavior */,
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
const merged = new RangeMap<K, V>(a.offsetKey, a.subtractKeys);
|
|
166
195
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
196
|
+
// TODO: Is there a good pattern that lets us make `tree` readonly?
|
|
197
|
+
merged.tree = a.tree.clone();
|
|
198
|
+
for (const [key, value] of b.tree.entries()) {
|
|
199
|
+
// TODO: Handle key collisions
|
|
200
|
+
merged.tree.set(key, value);
|
|
170
201
|
}
|
|
171
202
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if (entry
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
// Update the endpoint and length of the portion before the range to be deleted
|
|
187
|
-
const lengthBefore = start - entry.start;
|
|
188
|
-
this.entries[i] = { ...entry, length: lengthBefore };
|
|
189
|
-
isDirty = true;
|
|
203
|
+
return merged;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private getIntersectingEntries(start: K, length: number): RangeQueryEntry<K, V>[] {
|
|
207
|
+
const entries: RangeQueryEntry<K, V>[] = [];
|
|
208
|
+
const lastQueryKey = this.offsetKey(start, length - 1);
|
|
209
|
+
{
|
|
210
|
+
const entry = this.tree.getPairOrNextLower(start);
|
|
211
|
+
if (entry !== undefined) {
|
|
212
|
+
const key = entry[0];
|
|
213
|
+
const { length: entryLength, value } = entry[1];
|
|
214
|
+
const lastEntryKey = this.offsetKey(key, entryLength - 1);
|
|
215
|
+
if (this.ge(lastEntryKey, start)) {
|
|
216
|
+
entries.push({ start: key, length: entryLength, value });
|
|
190
217
|
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
191
220
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
length: newLength,
|
|
199
|
-
value: entry.value,
|
|
200
|
-
});
|
|
221
|
+
{
|
|
222
|
+
let entry = this.tree.nextHigherPair(start);
|
|
223
|
+
while (entry !== undefined) {
|
|
224
|
+
const key = entry[0];
|
|
225
|
+
if (this.gt(key, lastQueryKey)) {
|
|
226
|
+
break;
|
|
201
227
|
}
|
|
228
|
+
|
|
229
|
+
const { length: entryLength, value } = entry[1];
|
|
230
|
+
const lastEntryKey = this.offsetKey(key, entryLength - 1);
|
|
231
|
+
|
|
232
|
+
entries.push({ start: key, length: entryLength, value });
|
|
233
|
+
entry = this.tree.nextHigherPair(lastEntryKey);
|
|
202
234
|
}
|
|
203
235
|
}
|
|
236
|
+
|
|
237
|
+
return entries;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
private gt(a: K, b: K): boolean {
|
|
241
|
+
return this.subtractKeys(a, b) > 0;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
private ge(a: K, b: K): boolean {
|
|
245
|
+
return this.subtractKeys(a, b) >= 0;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
private lt(a: K, b: K): boolean {
|
|
249
|
+
return this.subtractKeys(a, b) < 0;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
private le(a: K, b: K): boolean {
|
|
253
|
+
return this.subtractKeys(a, b) <= 0;
|
|
204
254
|
}
|
|
205
255
|
}
|
|
206
256
|
|
|
207
257
|
/**
|
|
208
258
|
* Represents a contiguous range of values in the RangeMap.
|
|
209
|
-
* This interface is used internally and should not be exposed to consumers.
|
|
210
259
|
*/
|
|
211
|
-
interface RangeEntry<
|
|
212
|
-
/**
|
|
213
|
-
* The starting index of the range (inclusive).
|
|
214
|
-
*/
|
|
215
|
-
readonly start: number;
|
|
216
|
-
|
|
260
|
+
interface RangeEntry<V> {
|
|
217
261
|
/**
|
|
218
262
|
* The length of the range.
|
|
219
263
|
*/
|
|
@@ -222,18 +266,23 @@ interface RangeEntry<T> {
|
|
|
222
266
|
/**
|
|
223
267
|
* The value associated with this range.
|
|
224
268
|
*/
|
|
225
|
-
readonly value:
|
|
269
|
+
readonly value: V;
|
|
226
270
|
}
|
|
227
271
|
|
|
228
272
|
/**
|
|
229
273
|
* Describes the result of a range query, including the value and length of the matching prefix.
|
|
230
274
|
*/
|
|
231
|
-
export interface RangeQueryResult<
|
|
275
|
+
export interface RangeQueryResult<K, V> {
|
|
276
|
+
/**
|
|
277
|
+
* The key for the first element in the range.
|
|
278
|
+
*/
|
|
279
|
+
readonly start: K;
|
|
280
|
+
|
|
232
281
|
/**
|
|
233
282
|
* The value of the first key in the query range.
|
|
234
283
|
* If no matching range is found, this will be undefined.
|
|
235
284
|
*/
|
|
236
|
-
readonly value:
|
|
285
|
+
readonly value: V | undefined;
|
|
237
286
|
|
|
238
287
|
/**
|
|
239
288
|
* The length of the prefix of the query range which has the same value.
|
|
@@ -242,3 +291,19 @@ export interface RangeQueryResult<T> {
|
|
|
242
291
|
*/
|
|
243
292
|
readonly length: number;
|
|
244
293
|
}
|
|
294
|
+
|
|
295
|
+
export interface RangeQueryEntry<K, V> extends RangeQueryResult<K, V> {
|
|
296
|
+
readonly value: V;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export function newIntegerRangeMap<V>(): RangeMap<number, V> {
|
|
300
|
+
return new RangeMap(offsetInteger, subtractIntegers);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function offsetInteger(key: number, offset: number): number {
|
|
304
|
+
return key + offset;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function subtractIntegers(a: number, b: number): number {
|
|
308
|
+
return a - b;
|
|
309
|
+
}
|
package/src/util/utils.ts
CHANGED
|
@@ -48,9 +48,16 @@ export function asMutable<T>(readonly: T): Mutable<T> {
|
|
|
48
48
|
export const clone = structuredClone;
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
* Throw an error with a constant message.
|
|
52
|
+
* @remarks
|
|
53
|
+
* Works like {@link @fluidframework/core-utils/internal#assert}.
|
|
54
|
+
*/
|
|
55
|
+
export function fail(message: string | number): never {
|
|
56
|
+
// Declaring this here aliased to a different name avoids the assert tagging objecting to the usages of `assert` below.
|
|
57
|
+
// Since users of `fail` do the assert message tagging instead, suppressing tagging errors here makes sense.
|
|
58
|
+
const assertNoTag: (condition: boolean, message: string | number) => asserts condition =
|
|
59
|
+
assert;
|
|
60
|
+
assertNoTag(false, message);
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
/**
|
package/lib/package.json
DELETED