@fluidframework/sequence 2.0.0-internal.5.3.2 → 2.0.0-internal.5.4.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 +38 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -9
- package/dist/index.js.map +1 -1
- package/dist/intervalCollection.d.ts +46 -410
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +44 -732
- package/dist/intervalCollection.js.map +1 -1
- package/dist/intervalIndex/endpointInRangeIndex.d.ts +20 -0
- package/dist/intervalIndex/endpointInRangeIndex.d.ts.map +1 -0
- package/dist/intervalIndex/endpointInRangeIndex.js +60 -0
- package/dist/intervalIndex/endpointInRangeIndex.js.map +1 -0
- package/dist/intervalIndex/endpointIndex.d.ts +21 -0
- package/dist/intervalIndex/endpointIndex.d.ts.map +1 -0
- package/dist/intervalIndex/endpointIndex.js +42 -0
- package/dist/intervalIndex/endpointIndex.js.map +1 -0
- package/dist/intervalIndex/idIntervalIndex.d.ts +12 -0
- package/dist/intervalIndex/idIntervalIndex.d.ts.map +1 -0
- package/dist/intervalIndex/idIntervalIndex.js +41 -0
- package/dist/intervalIndex/idIntervalIndex.js.map +1 -0
- package/dist/intervalIndex/index.d.ts +5 -0
- package/dist/intervalIndex/index.d.ts.map +1 -1
- package/dist/intervalIndex/index.js +9 -1
- package/dist/intervalIndex/index.js.map +1 -1
- package/dist/intervalIndex/intervalIndex.d.ts +29 -0
- package/dist/intervalIndex/intervalIndex.d.ts.map +1 -0
- package/dist/intervalIndex/intervalIndex.js +7 -0
- package/dist/intervalIndex/intervalIndex.js.map +1 -0
- package/dist/intervalIndex/intervalIndexUtils.d.ts +17 -0
- package/dist/intervalIndex/intervalIndexUtils.d.ts.map +1 -0
- package/dist/intervalIndex/intervalIndexUtils.js +23 -0
- package/dist/intervalIndex/intervalIndexUtils.js.map +1 -0
- package/dist/intervalIndex/overlappingIntervalsIndex.d.ts +2 -1
- package/dist/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
- package/dist/intervalIndex/overlappingIntervalsIndex.js +3 -3
- package/dist/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js +5 -5
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js.map +1 -1
- package/dist/intervalIndex/sequenceIntervalIndexes.d.ts +1 -1
- package/dist/intervalIndex/sequenceIntervalIndexes.d.ts.map +1 -1
- package/dist/intervalIndex/sequenceIntervalIndexes.js.map +1 -1
- package/dist/intervalIndex/startpointInRangeIndex.d.ts +20 -0
- package/dist/intervalIndex/startpointInRangeIndex.d.ts.map +1 -0
- package/dist/intervalIndex/startpointInRangeIndex.js +62 -0
- package/dist/intervalIndex/startpointInRangeIndex.js.map +1 -0
- package/dist/intervalTree.d.ts +1 -47
- package/dist/intervalTree.d.ts.map +1 -1
- package/dist/intervalTree.js.map +1 -1
- package/dist/intervals/index.d.ts +8 -0
- package/dist/intervals/index.d.ts.map +1 -0
- package/dist/intervals/index.js +23 -0
- package/dist/intervals/index.js.map +1 -0
- package/dist/intervals/interval.d.ts +88 -0
- package/dist/intervals/interval.d.ts.map +1 -0
- package/dist/intervals/interval.js +182 -0
- package/dist/intervals/interval.js.map +1 -0
- package/dist/intervals/intervalUtils.d.ts +194 -0
- package/dist/intervals/intervalUtils.d.ts.map +1 -0
- package/dist/intervals/intervalUtils.js +79 -0
- package/dist/intervals/intervalUtils.js.map +1 -0
- package/dist/intervals/sequenceInterval.d.ts +132 -0
- package/dist/intervals/sequenceInterval.d.ts.map +1 -0
- package/dist/intervals/sequenceInterval.js +315 -0
- package/dist/intervals/sequenceInterval.js.map +1 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/revertibles.d.ts +1 -1
- package/dist/revertibles.d.ts.map +1 -1
- package/dist/revertibles.js +36 -29
- package/dist/revertibles.js.map +1 -1
- package/dist/sequence.d.ts +2 -1
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +4 -1
- package/dist/sequence.js.map +1 -1
- package/dist/sharedIntervalCollection.d.ts +2 -1
- package/dist/sharedIntervalCollection.d.ts.map +1 -1
- package/dist/sharedIntervalCollection.js.map +1 -1
- package/lib/index.d.ts +4 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -2
- package/lib/index.js.map +1 -1
- package/lib/intervalCollection.d.ts +46 -410
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +25 -705
- package/lib/intervalCollection.js.map +1 -1
- package/lib/intervalIndex/endpointInRangeIndex.d.ts +20 -0
- package/lib/intervalIndex/endpointInRangeIndex.d.ts.map +1 -0
- package/lib/intervalIndex/endpointInRangeIndex.js +56 -0
- package/lib/intervalIndex/endpointInRangeIndex.js.map +1 -0
- package/lib/intervalIndex/endpointIndex.d.ts +21 -0
- package/lib/intervalIndex/endpointIndex.d.ts.map +1 -0
- package/lib/intervalIndex/endpointIndex.js +38 -0
- package/lib/intervalIndex/endpointIndex.js.map +1 -0
- package/lib/intervalIndex/idIntervalIndex.d.ts +12 -0
- package/lib/intervalIndex/idIntervalIndex.d.ts.map +1 -0
- package/lib/intervalIndex/idIntervalIndex.js +37 -0
- package/lib/intervalIndex/idIntervalIndex.js.map +1 -0
- package/lib/intervalIndex/index.d.ts +5 -0
- package/lib/intervalIndex/index.d.ts.map +1 -1
- package/lib/intervalIndex/index.js +4 -0
- package/lib/intervalIndex/index.js.map +1 -1
- package/lib/intervalIndex/intervalIndex.d.ts +29 -0
- package/lib/intervalIndex/intervalIndex.d.ts.map +1 -0
- package/lib/intervalIndex/intervalIndex.js +6 -0
- package/lib/intervalIndex/intervalIndex.js.map +1 -0
- package/lib/intervalIndex/intervalIndexUtils.d.ts +17 -0
- package/lib/intervalIndex/intervalIndexUtils.d.ts.map +1 -0
- package/lib/intervalIndex/intervalIndexUtils.js +19 -0
- package/lib/intervalIndex/intervalIndexUtils.js.map +1 -0
- package/lib/intervalIndex/overlappingIntervalsIndex.d.ts +2 -1
- package/lib/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
- package/lib/intervalIndex/overlappingIntervalsIndex.js +1 -1
- package/lib/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js +1 -1
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js.map +1 -1
- package/lib/intervalIndex/sequenceIntervalIndexes.d.ts +1 -1
- package/lib/intervalIndex/sequenceIntervalIndexes.d.ts.map +1 -1
- package/lib/intervalIndex/sequenceIntervalIndexes.js.map +1 -1
- package/lib/intervalIndex/startpointInRangeIndex.d.ts +20 -0
- package/lib/intervalIndex/startpointInRangeIndex.d.ts.map +1 -0
- package/lib/intervalIndex/startpointInRangeIndex.js +58 -0
- package/lib/intervalIndex/startpointInRangeIndex.js.map +1 -0
- package/lib/intervalTree.d.ts +1 -47
- package/lib/intervalTree.d.ts.map +1 -1
- package/lib/intervalTree.js.map +1 -1
- package/lib/intervals/index.d.ts +8 -0
- package/lib/intervals/index.d.ts.map +1 -0
- package/lib/intervals/index.js +8 -0
- package/lib/intervals/index.js.map +1 -0
- package/lib/intervals/interval.d.ts +88 -0
- package/lib/intervals/interval.d.ts.map +1 -0
- package/lib/intervals/interval.js +177 -0
- package/lib/intervals/interval.js.map +1 -0
- package/lib/intervals/intervalUtils.d.ts +194 -0
- package/lib/intervals/intervalUtils.d.ts.map +1 -0
- package/lib/intervals/intervalUtils.js +74 -0
- package/lib/intervals/intervalUtils.js.map +1 -0
- package/lib/intervals/sequenceInterval.d.ts +132 -0
- package/lib/intervals/sequenceInterval.d.ts.map +1 -0
- package/lib/intervals/sequenceInterval.js +307 -0
- package/lib/intervals/sequenceInterval.js.map +1 -0
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/revertibles.d.ts +1 -1
- package/lib/revertibles.d.ts.map +1 -1
- package/lib/revertibles.js +21 -14
- package/lib/revertibles.js.map +1 -1
- package/lib/sequence.d.ts +2 -1
- package/lib/sequence.d.ts.map +1 -1
- package/lib/sequence.js +5 -2
- package/lib/sequence.js.map +1 -1
- package/lib/sharedIntervalCollection.d.ts +2 -1
- package/lib/sharedIntervalCollection.d.ts.map +1 -1
- package/lib/sharedIntervalCollection.js.map +1 -1
- package/package.json +15 -15
- package/src/index.ts +19 -12
- package/src/intervalCollection.ts +75 -1204
- package/src/intervalIndex/endpointInRangeIndex.ts +104 -0
- package/src/intervalIndex/endpointIndex.ts +78 -0
- package/src/intervalIndex/idIntervalIndex.ts +58 -0
- package/src/intervalIndex/index.ts +5 -0
- package/src/intervalIndex/intervalIndex.ts +31 -0
- package/src/intervalIndex/intervalIndexUtils.ts +27 -0
- package/src/intervalIndex/overlappingIntervalsIndex.ts +2 -6
- package/src/intervalIndex/overlappingSequenceIntervalsIndex.ts +1 -1
- package/src/intervalIndex/sequenceIntervalIndexes.ts +1 -1
- package/src/intervalIndex/startpointInRangeIndex.ts +109 -0
- package/src/intervalTree.ts +1 -54
- package/src/intervals/index.ts +25 -0
- package/src/intervals/interval.ts +230 -0
- package/src/intervals/intervalUtils.ts +249 -0
- package/src/intervals/sequenceInterval.ts +494 -0
- package/src/packageVersion.ts +1 -1
- package/src/revertibles.ts +23 -12
- package/src/sequence.ts +6 -3
- package/src/sharedIntervalCollection.ts +1 -2
|
@@ -11,26 +11,17 @@ import { UsageError } from "@fluidframework/container-utils";
|
|
|
11
11
|
import {
|
|
12
12
|
addProperties,
|
|
13
13
|
Client,
|
|
14
|
-
compareReferencePositions,
|
|
15
14
|
createMap,
|
|
16
15
|
getSlideToSegoff,
|
|
17
|
-
ICombiningOp,
|
|
18
16
|
ISegment,
|
|
19
17
|
MergeTreeDeltaType,
|
|
20
|
-
minReferencePosition,
|
|
21
|
-
PropertiesManager,
|
|
22
18
|
PropertySet,
|
|
23
|
-
RedBlackTree,
|
|
24
19
|
LocalReferencePosition,
|
|
25
20
|
ReferenceType,
|
|
26
21
|
refTypeIncludesFlag,
|
|
27
22
|
reservedRangeLabelsKey,
|
|
28
23
|
UnassignedSequenceNumber,
|
|
29
|
-
maxReferencePosition,
|
|
30
|
-
createDetachedLocalReferencePosition,
|
|
31
24
|
DetachedReferencePosition,
|
|
32
|
-
SlidingPreference,
|
|
33
|
-
PropertyAction,
|
|
34
25
|
} from "@fluidframework/merge-tree";
|
|
35
26
|
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
36
27
|
import { LoggingError } from "@fluidframework/telemetry-utils";
|
|
@@ -44,87 +35,36 @@ import {
|
|
|
44
35
|
IValueTypeOperationValue,
|
|
45
36
|
SequenceOptions,
|
|
46
37
|
} from "./defaultMapInterfaces";
|
|
47
|
-
import {
|
|
48
|
-
import {
|
|
38
|
+
import { IntervalConflictResolver } from "./intervalTree";
|
|
39
|
+
import {
|
|
40
|
+
CompressedSerializedInterval,
|
|
41
|
+
IIntervalHelpers,
|
|
42
|
+
Interval,
|
|
43
|
+
IntervalOpType,
|
|
44
|
+
IntervalStickiness,
|
|
45
|
+
IntervalType,
|
|
46
|
+
ISerializableInterval,
|
|
47
|
+
ISerializedInterval,
|
|
48
|
+
SequenceInterval,
|
|
49
|
+
SerializedIntervalDelta,
|
|
50
|
+
createPositionReferenceFromSegoff,
|
|
51
|
+
endReferenceSlidingPreference,
|
|
52
|
+
startReferenceSlidingPreference,
|
|
53
|
+
sequenceIntervalHelpers,
|
|
54
|
+
createInterval,
|
|
55
|
+
} from "./intervals";
|
|
56
|
+
import {
|
|
57
|
+
IEndpointIndex,
|
|
58
|
+
IIdIntervalIndex,
|
|
59
|
+
IOverlappingIntervalsIndex,
|
|
60
|
+
IntervalIndex,
|
|
61
|
+
createEndpointIndex,
|
|
62
|
+
createIdIntervalIndex,
|
|
63
|
+
createOverlappingIntervalsIndex,
|
|
64
|
+
} from "./intervalIndex";
|
|
49
65
|
|
|
50
66
|
const reservedIntervalIdKey = "intervalId";
|
|
51
67
|
|
|
52
|
-
/**
|
|
53
|
-
* Values are used in persisted formats (ops) and revertibles.
|
|
54
|
-
* @alpha
|
|
55
|
-
*/
|
|
56
|
-
export const IntervalOpType = {
|
|
57
|
-
ADD: "add",
|
|
58
|
-
DELETE: "delete",
|
|
59
|
-
CHANGE: "change",
|
|
60
|
-
PROPERTY_CHANGED: "propertyChanged",
|
|
61
|
-
POSITION_REMOVE: "positionRemove",
|
|
62
|
-
} as const;
|
|
63
|
-
|
|
64
|
-
export enum IntervalType {
|
|
65
|
-
Simple = 0x0,
|
|
66
|
-
Nest = 0x1,
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* SlideOnRemove indicates that the ends of the interval will slide if the segment
|
|
70
|
-
* they reference is removed and acked.
|
|
71
|
-
* See `packages\dds\merge-tree\docs\REFERENCEPOSITIONS.md` for details
|
|
72
|
-
* SlideOnRemove is the default interval behavior and does not need to be specified.
|
|
73
|
-
*/
|
|
74
|
-
SlideOnRemove = 0x2, // SlideOnRemove is default behavior - all intervals are SlideOnRemove
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* A temporary interval, used internally
|
|
78
|
-
* @internal
|
|
79
|
-
*/
|
|
80
|
-
Transient = 0x4,
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Serialized object representation of an interval.
|
|
85
|
-
* This representation is used for ops that create or change intervals.
|
|
86
|
-
* @internal
|
|
87
|
-
*/
|
|
88
|
-
export interface ISerializedInterval {
|
|
89
|
-
/**
|
|
90
|
-
* Sequence number at which `start` and `end` should be interpreted
|
|
91
|
-
*
|
|
92
|
-
* @remarks - It's unclear that this is necessary to store here.
|
|
93
|
-
* This should just be the refSeq on the op that modified the interval, which should be available via other means.
|
|
94
|
-
* At the time of writing, it's not plumbed through to the reconnect/rebase code, however, which does need it.
|
|
95
|
-
*/
|
|
96
|
-
sequenceNumber: number;
|
|
97
|
-
/** Start position of the interval */
|
|
98
|
-
start: number;
|
|
99
|
-
/** End position of the interval */
|
|
100
|
-
end: number;
|
|
101
|
-
/** Interval type to create */
|
|
102
|
-
intervalType: IntervalType;
|
|
103
|
-
stickiness?: IntervalStickiness;
|
|
104
|
-
/** Any properties the interval has */
|
|
105
|
-
properties?: PropertySet;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Represents a change that should be applied to an existing interval.
|
|
110
|
-
* Changes can modify any of start/end/properties, with `undefined` signifying no change should be made.
|
|
111
|
-
* @internal
|
|
112
|
-
*/
|
|
113
|
-
export type SerializedIntervalDelta = Omit<ISerializedInterval, "start" | "end" | "properties"> &
|
|
114
|
-
Partial<Pick<ISerializedInterval, "start" | "end" | "properties">>;
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* A size optimization to avoid redundantly storing keys when serializing intervals
|
|
118
|
-
* as JSON for summaries.
|
|
119
|
-
*
|
|
120
|
-
* Intervals are of the format:
|
|
121
|
-
*
|
|
122
|
-
* [start, end, sequenceNumber, intervalType, properties, stickiness?]
|
|
123
|
-
*/
|
|
124
|
-
export type CompressedSerializedInterval =
|
|
125
|
-
| [number, number, number, IntervalType, PropertySet, IntervalStickiness]
|
|
126
|
-
| [number, number, number, IntervalType, PropertySet];
|
|
127
|
-
|
|
128
68
|
export interface ISerializedIntervalCollectionV2 {
|
|
129
69
|
label: string;
|
|
130
70
|
version: 2;
|
|
@@ -173,1091 +113,20 @@ function compressInterval(interval: ISerializedInterval): CompressedSerializedIn
|
|
|
173
113
|
return base;
|
|
174
114
|
}
|
|
175
115
|
|
|
176
|
-
function startReferenceSlidingPreference(stickiness: IntervalStickiness): SlidingPreference {
|
|
177
|
-
// if any start stickiness, prefer sliding backwards
|
|
178
|
-
return (stickiness & IntervalStickiness.START) !== 0
|
|
179
|
-
? SlidingPreference.BACKWARD
|
|
180
|
-
: SlidingPreference.FORWARD;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function endReferenceSlidingPreference(stickiness: IntervalStickiness): SlidingPreference {
|
|
184
|
-
// if any end stickiness, prefer sliding forwards
|
|
185
|
-
return (stickiness & IntervalStickiness.END) !== 0
|
|
186
|
-
? SlidingPreference.FORWARD
|
|
187
|
-
: SlidingPreference.BACKWARD;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export interface ISerializableInterval extends IInterval {
|
|
191
|
-
/** Serializable bag of properties associated with the interval. */
|
|
192
|
-
properties: PropertySet;
|
|
193
|
-
/** @internal */
|
|
194
|
-
propertyManager: PropertiesManager;
|
|
195
|
-
/** @internal */
|
|
196
|
-
serialize(): ISerializedInterval;
|
|
197
|
-
/** @internal */
|
|
198
|
-
addProperties(
|
|
199
|
-
props: PropertySet,
|
|
200
|
-
collaborating?: boolean,
|
|
201
|
-
seq?: number,
|
|
202
|
-
): PropertySet | undefined;
|
|
203
|
-
/**
|
|
204
|
-
* Gets the id associated with this interval.
|
|
205
|
-
* When the interval is used as part of an interval collection, this id can be used to modify or remove the
|
|
206
|
-
* interval.
|
|
207
|
-
* @remarks - This signature includes `undefined` strictly for backwards-compatibility reasons, as older versions
|
|
208
|
-
* of Fluid didn't always write interval ids.
|
|
209
|
-
*/
|
|
210
|
-
getIntervalId(): string | undefined;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* @sealed
|
|
215
|
-
*/
|
|
216
|
-
export interface IIntervalHelpers<TInterval extends ISerializableInterval> {
|
|
217
|
-
compareEnds(a: TInterval, b: TInterval): number;
|
|
218
|
-
compareStarts?(a: TInterval, b: TInterval): number;
|
|
219
|
-
/**
|
|
220
|
-
*
|
|
221
|
-
* @param label - label of the interval collection this interval is being added to. This parameter is
|
|
222
|
-
* irrelevant for transient intervals.
|
|
223
|
-
* @param start - numerical start position of the interval
|
|
224
|
-
* @param end - numerical end position of the interval
|
|
225
|
-
* @param client - client creating the interval
|
|
226
|
-
* @param intervalType - Type of interval to create. Default is SlideOnRemove
|
|
227
|
-
* @param op - If this create came from a remote client, op that created it. Default is undefined (i.e. local)
|
|
228
|
-
* @param fromSnapshot - If this create came from loading a snapshot. Default is false.
|
|
229
|
-
*/
|
|
230
|
-
create(
|
|
231
|
-
label: string,
|
|
232
|
-
start: number | undefined,
|
|
233
|
-
end: number | undefined,
|
|
234
|
-
client: Client | undefined,
|
|
235
|
-
intervalType: IntervalType,
|
|
236
|
-
op?: ISequencedDocumentMessage,
|
|
237
|
-
fromSnapshot?: boolean,
|
|
238
|
-
stickiness?: IntervalStickiness,
|
|
239
|
-
): TInterval;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Determines how an interval should expand when segments are inserted adjacent
|
|
244
|
-
* to the range it spans
|
|
245
|
-
*
|
|
246
|
-
* Note that interval stickiness is currently an experimental feature and must
|
|
247
|
-
* be explicitly enabled with the `intervalStickinessEnabled` flag
|
|
248
|
-
*/
|
|
249
|
-
export const IntervalStickiness = {
|
|
250
|
-
/**
|
|
251
|
-
* Interval does not expand to include adjacent segments
|
|
252
|
-
*/
|
|
253
|
-
NONE: 0b00,
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Interval expands to include segments inserted adjacent to the start
|
|
257
|
-
*/
|
|
258
|
-
START: 0b01,
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Interval expands to include segments inserted adjacent to the end
|
|
262
|
-
*
|
|
263
|
-
* This is the default stickiness
|
|
264
|
-
*/
|
|
265
|
-
END: 0b10,
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Interval expands to include all segments inserted adjacent to it
|
|
269
|
-
*/
|
|
270
|
-
FULL: 0b11,
|
|
271
|
-
} as const;
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Determines how an interval should expand when segments are inserted adjacent
|
|
275
|
-
* to the range it spans
|
|
276
|
-
*
|
|
277
|
-
* Note that interval stickiness is currently an experimental feature and must
|
|
278
|
-
* be explicitly enabled with the `intervalStickinessEnabled` flag
|
|
279
|
-
*/
|
|
280
|
-
export type IntervalStickiness = typeof IntervalStickiness[keyof typeof IntervalStickiness];
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Serializable interval whose endpoints are plain-old numbers.
|
|
284
|
-
*/
|
|
285
|
-
export class Interval implements ISerializableInterval {
|
|
286
|
-
/**
|
|
287
|
-
* {@inheritDoc ISerializableInterval.properties}
|
|
288
|
-
*/
|
|
289
|
-
public properties: PropertySet;
|
|
290
|
-
/** @internal */
|
|
291
|
-
public auxProps: PropertySet[] | undefined;
|
|
292
|
-
/**
|
|
293
|
-
* {@inheritDoc ISerializableInterval.propertyManager}
|
|
294
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
295
|
-
*/
|
|
296
|
-
public propertyManager: PropertiesManager;
|
|
297
|
-
constructor(public start: number, public end: number, props?: PropertySet) {
|
|
298
|
-
this.propertyManager = new PropertiesManager();
|
|
299
|
-
this.properties = {};
|
|
300
|
-
|
|
301
|
-
if (props) {
|
|
302
|
-
this.addProperties(props);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* {@inheritDoc ISerializableInterval.getIntervalId}
|
|
308
|
-
*/
|
|
309
|
-
public getIntervalId(): string {
|
|
310
|
-
const id = this.properties?.[reservedIntervalIdKey];
|
|
311
|
-
assert(id !== undefined, 0x5e1 /* interval ID should not be undefined */);
|
|
312
|
-
return `${id}`;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
/**
|
|
316
|
-
* @returns an array containing any auxiliary property sets added with `addPropertySet`.
|
|
317
|
-
*/
|
|
318
|
-
public getAdditionalPropertySets(): PropertySet[] {
|
|
319
|
-
return this.auxProps ?? [];
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Adds an auxiliary set of properties to this interval.
|
|
324
|
-
* These properties can be recovered using `getAdditionalPropertySets`
|
|
325
|
-
* @param props - set of properties to add
|
|
326
|
-
* @remarks - This gets called as part of the default conflict resolver for `IIntervalCollection<Interval>`
|
|
327
|
-
* (i.e. non-sequence-based interval collections). However, the additional properties don't get serialized.
|
|
328
|
-
* This functionality seems half-baked.
|
|
329
|
-
*/
|
|
330
|
-
public addPropertySet(props: PropertySet) {
|
|
331
|
-
if (this.auxProps === undefined) {
|
|
332
|
-
this.auxProps = [];
|
|
333
|
-
}
|
|
334
|
-
this.auxProps.push(props);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* {@inheritDoc ISerializableInterval.serialize}
|
|
339
|
-
* @internal
|
|
340
|
-
*/
|
|
341
|
-
public serialize(): ISerializedInterval {
|
|
342
|
-
const serializedInterval: ISerializedInterval = {
|
|
343
|
-
end: this.end,
|
|
344
|
-
intervalType: 0,
|
|
345
|
-
sequenceNumber: 0,
|
|
346
|
-
start: this.start,
|
|
347
|
-
};
|
|
348
|
-
if (this.properties) {
|
|
349
|
-
serializedInterval.properties = this.properties;
|
|
350
|
-
}
|
|
351
|
-
return serializedInterval;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* {@inheritDoc IInterval.clone}
|
|
356
|
-
*/
|
|
357
|
-
public clone() {
|
|
358
|
-
return new Interval(this.start, this.end, this.properties);
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* {@inheritDoc IInterval.compare}
|
|
363
|
-
*/
|
|
364
|
-
public compare(b: Interval) {
|
|
365
|
-
const startResult = this.compareStart(b);
|
|
366
|
-
if (startResult === 0) {
|
|
367
|
-
const endResult = this.compareEnd(b);
|
|
368
|
-
if (endResult === 0) {
|
|
369
|
-
const thisId = this.getIntervalId();
|
|
370
|
-
if (thisId) {
|
|
371
|
-
const bId = b.getIntervalId();
|
|
372
|
-
if (bId) {
|
|
373
|
-
return thisId > bId ? 1 : thisId < bId ? -1 : 0;
|
|
374
|
-
}
|
|
375
|
-
return 0;
|
|
376
|
-
}
|
|
377
|
-
return 0;
|
|
378
|
-
} else {
|
|
379
|
-
return endResult;
|
|
380
|
-
}
|
|
381
|
-
} else {
|
|
382
|
-
return startResult;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* {@inheritDoc IInterval.compareStart}
|
|
388
|
-
*/
|
|
389
|
-
public compareStart(b: Interval) {
|
|
390
|
-
return this.start - b.start;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
/**
|
|
394
|
-
* {@inheritDoc IInterval.compareEnd}
|
|
395
|
-
*/
|
|
396
|
-
public compareEnd(b: Interval) {
|
|
397
|
-
return this.end - b.end;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* {@inheritDoc IInterval.overlaps}
|
|
402
|
-
*/
|
|
403
|
-
public overlaps(b: Interval) {
|
|
404
|
-
const result = this.start <= b.end && this.end >= b.start;
|
|
405
|
-
return result;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* {@inheritDoc IInterval.union}
|
|
410
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
411
|
-
*/
|
|
412
|
-
public union(b: Interval) {
|
|
413
|
-
return new Interval(
|
|
414
|
-
Math.min(this.start, b.start),
|
|
415
|
-
Math.max(this.end, b.end),
|
|
416
|
-
this.properties,
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
public getProperties() {
|
|
421
|
-
return this.properties;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
/**
|
|
425
|
-
* {@inheritDoc ISerializableInterval.addProperties}
|
|
426
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
427
|
-
*/
|
|
428
|
-
public addProperties(
|
|
429
|
-
newProps: PropertySet,
|
|
430
|
-
collaborating: boolean = false,
|
|
431
|
-
seq?: number,
|
|
432
|
-
op?: ICombiningOp,
|
|
433
|
-
): PropertySet | undefined {
|
|
434
|
-
if (newProps) {
|
|
435
|
-
this.initializeProperties();
|
|
436
|
-
return this.propertyManager.addProperties(
|
|
437
|
-
this.properties,
|
|
438
|
-
newProps,
|
|
439
|
-
op,
|
|
440
|
-
seq,
|
|
441
|
-
collaborating,
|
|
442
|
-
);
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
/**
|
|
447
|
-
* {@inheritDoc IInterval.modify}
|
|
448
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
449
|
-
*/
|
|
450
|
-
public modify(label: string, start: number, end: number, op?: ISequencedDocumentMessage) {
|
|
451
|
-
const startPos = start ?? this.start;
|
|
452
|
-
const endPos = end ?? this.end;
|
|
453
|
-
if (this.start === startPos && this.end === endPos) {
|
|
454
|
-
// Return undefined to indicate that no change is necessary.
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
457
|
-
const newInterval = new Interval(startPos, endPos);
|
|
458
|
-
if (this.properties) {
|
|
459
|
-
newInterval.initializeProperties();
|
|
460
|
-
this.propertyManager.copyTo(
|
|
461
|
-
this.properties,
|
|
462
|
-
newInterval.properties,
|
|
463
|
-
newInterval.propertyManager,
|
|
464
|
-
);
|
|
465
|
-
}
|
|
466
|
-
return newInterval;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
private initializeProperties(): void {
|
|
470
|
-
if (!this.propertyManager) {
|
|
471
|
-
this.propertyManager = new PropertiesManager();
|
|
472
|
-
}
|
|
473
|
-
if (!this.properties) {
|
|
474
|
-
this.properties = createMap<any>();
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
/**
|
|
480
|
-
* Interval implementation whose ends are associated with positions in a mutatable sequence.
|
|
481
|
-
* As such, when content is inserted into the middle of the interval, the interval expands to
|
|
482
|
-
* include that content.
|
|
483
|
-
*
|
|
484
|
-
* @remarks - The endpoint's position should be treated exclusively to get reasonable behavior--i.e.
|
|
485
|
-
* an interval referring to "hello" in "hello world" should have a start position of 0 and an end
|
|
486
|
-
* position of 5.
|
|
487
|
-
*
|
|
488
|
-
* To see why, consider what happens if "llo wor" is removed from the string to make "held".
|
|
489
|
-
* The interval's startpoint remains on the "h" (it isn't altered), but the interval's endpoint
|
|
490
|
-
* slides forward to the next unremoved position, which is the "l" in "held".
|
|
491
|
-
* Users would generally expect the interval to now refer to "he" (as it is the subset of content
|
|
492
|
-
* remaining after the removal), hence the "l" should be excluded.
|
|
493
|
-
* If the interval endpoint was treated inclusively, the interval would now refer to "hel", which
|
|
494
|
-
* is undesirable.
|
|
495
|
-
*
|
|
496
|
-
* Since the end of an interval is treated exclusively but cannot be greater than or equal to the
|
|
497
|
-
* length of the associated sequence, application models which leverage interval collections should
|
|
498
|
-
* consider inserting a marker at the end of the sequence to represent the end of the content.
|
|
499
|
-
*/
|
|
500
|
-
export class SequenceInterval implements ISerializableInterval {
|
|
501
|
-
/**
|
|
502
|
-
* {@inheritDoc ISerializableInterval.properties}
|
|
503
|
-
*/
|
|
504
|
-
public properties: PropertySet;
|
|
505
|
-
/**
|
|
506
|
-
* {@inheritDoc ISerializableInterval.propertyManager}
|
|
507
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
508
|
-
*/
|
|
509
|
-
public propertyManager: PropertiesManager;
|
|
510
|
-
|
|
511
|
-
constructor(
|
|
512
|
-
private readonly client: Client,
|
|
513
|
-
/**
|
|
514
|
-
* Start endpoint of this interval.
|
|
515
|
-
* @remarks - This endpoint can be resolved into a character position using the SharedString it's a part of.
|
|
516
|
-
*/
|
|
517
|
-
public start: LocalReferencePosition,
|
|
518
|
-
/**
|
|
519
|
-
* End endpoint of this interval.
|
|
520
|
-
* @remarks - This endpoint can be resolved into a character position using the SharedString it's a part of.
|
|
521
|
-
*/
|
|
522
|
-
public end: LocalReferencePosition,
|
|
523
|
-
public intervalType: IntervalType,
|
|
524
|
-
props?: PropertySet,
|
|
525
|
-
public readonly stickiness: IntervalStickiness = IntervalStickiness.END,
|
|
526
|
-
) {
|
|
527
|
-
this.propertyManager = new PropertiesManager();
|
|
528
|
-
this.properties = {};
|
|
529
|
-
|
|
530
|
-
if (props) {
|
|
531
|
-
this.addProperties(props);
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
private callbacks?: Record<"beforePositionChange" | "afterPositionChange", () => void>;
|
|
536
|
-
|
|
537
|
-
/**
|
|
538
|
-
* Subscribes to position change events on this interval if there are no current listeners.
|
|
539
|
-
* @internal
|
|
540
|
-
*/
|
|
541
|
-
public addPositionChangeListeners(
|
|
542
|
-
beforePositionChange: () => void,
|
|
543
|
-
afterPositionChange: () => void,
|
|
544
|
-
): void {
|
|
545
|
-
if (this.callbacks === undefined) {
|
|
546
|
-
this.callbacks = {
|
|
547
|
-
beforePositionChange,
|
|
548
|
-
afterPositionChange,
|
|
549
|
-
};
|
|
550
|
-
|
|
551
|
-
const startCbs = (this.start.callbacks ??= {});
|
|
552
|
-
const endCbs = (this.end.callbacks ??= {});
|
|
553
|
-
startCbs.beforeSlide = endCbs.beforeSlide = beforePositionChange;
|
|
554
|
-
startCbs.afterSlide = endCbs.afterSlide = afterPositionChange;
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
/**
|
|
559
|
-
* Removes the currently subscribed position change listeners.
|
|
560
|
-
* @internal
|
|
561
|
-
*/
|
|
562
|
-
public removePositionChangeListeners(): void {
|
|
563
|
-
if (this.callbacks) {
|
|
564
|
-
this.callbacks = undefined;
|
|
565
|
-
this.start.callbacks = undefined;
|
|
566
|
-
this.end.callbacks = undefined;
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
/**
|
|
571
|
-
* {@inheritDoc ISerializableInterval.serialize}
|
|
572
|
-
* @internal
|
|
573
|
-
*/
|
|
574
|
-
public serialize(): ISerializedInterval {
|
|
575
|
-
const startPosition = this.client.localReferencePositionToPosition(this.start);
|
|
576
|
-
const endPosition = this.client.localReferencePositionToPosition(this.end);
|
|
577
|
-
const serializedInterval: ISerializedInterval = {
|
|
578
|
-
end: endPosition,
|
|
579
|
-
intervalType: this.intervalType,
|
|
580
|
-
sequenceNumber: this.client.getCurrentSeq(),
|
|
581
|
-
start: startPosition,
|
|
582
|
-
};
|
|
583
|
-
|
|
584
|
-
if (this.properties) {
|
|
585
|
-
serializedInterval.properties = this.properties;
|
|
586
|
-
}
|
|
587
|
-
if (this.stickiness !== IntervalStickiness.END) {
|
|
588
|
-
serializedInterval.stickiness = this.stickiness;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
return serializedInterval;
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
/**
|
|
595
|
-
* {@inheritDoc IInterval.clone}
|
|
596
|
-
*/
|
|
597
|
-
public clone() {
|
|
598
|
-
return new SequenceInterval(
|
|
599
|
-
this.client,
|
|
600
|
-
this.start,
|
|
601
|
-
this.end,
|
|
602
|
-
this.intervalType,
|
|
603
|
-
this.properties,
|
|
604
|
-
this.stickiness,
|
|
605
|
-
);
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
/**
|
|
609
|
-
* {@inheritDoc IInterval.compare}
|
|
610
|
-
*/
|
|
611
|
-
public compare(b: SequenceInterval) {
|
|
612
|
-
const startResult = this.compareStart(b);
|
|
613
|
-
if (startResult === 0) {
|
|
614
|
-
const endResult = this.compareEnd(b);
|
|
615
|
-
if (endResult === 0) {
|
|
616
|
-
const thisId = this.getIntervalId();
|
|
617
|
-
if (thisId) {
|
|
618
|
-
const bId = b.getIntervalId();
|
|
619
|
-
if (bId) {
|
|
620
|
-
return thisId > bId ? 1 : thisId < bId ? -1 : 0;
|
|
621
|
-
}
|
|
622
|
-
return 0;
|
|
623
|
-
}
|
|
624
|
-
return 0;
|
|
625
|
-
} else {
|
|
626
|
-
return endResult;
|
|
627
|
-
}
|
|
628
|
-
} else {
|
|
629
|
-
return startResult;
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
/**
|
|
634
|
-
* {@inheritDoc IInterval.compareStart}
|
|
635
|
-
*/
|
|
636
|
-
public compareStart(b: SequenceInterval) {
|
|
637
|
-
return compareReferencePositions(this.start, b.start);
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
/**
|
|
641
|
-
* {@inheritDoc IInterval.compareEnd}
|
|
642
|
-
*/
|
|
643
|
-
public compareEnd(b: SequenceInterval) {
|
|
644
|
-
return compareReferencePositions(this.end, b.end);
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
/**
|
|
648
|
-
* {@inheritDoc IInterval.overlaps}
|
|
649
|
-
*/
|
|
650
|
-
public overlaps(b: SequenceInterval) {
|
|
651
|
-
const result =
|
|
652
|
-
compareReferencePositions(this.start, b.end) <= 0 &&
|
|
653
|
-
compareReferencePositions(this.end, b.start) >= 0;
|
|
654
|
-
return result;
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
/**
|
|
658
|
-
* {@inheritDoc ISerializableInterval.getIntervalId}
|
|
659
|
-
*/
|
|
660
|
-
public getIntervalId(): string {
|
|
661
|
-
const id = this.properties?.[reservedIntervalIdKey];
|
|
662
|
-
assert(id !== undefined, 0x5e2 /* interval ID should not be undefined */);
|
|
663
|
-
return `${id}`;
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
/**
|
|
667
|
-
* {@inheritDoc IInterval.union}
|
|
668
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
669
|
-
*/
|
|
670
|
-
public union(b: SequenceInterval) {
|
|
671
|
-
return new SequenceInterval(
|
|
672
|
-
this.client,
|
|
673
|
-
minReferencePosition(this.start, b.start),
|
|
674
|
-
maxReferencePosition(this.end, b.end),
|
|
675
|
-
this.intervalType,
|
|
676
|
-
);
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
/**
|
|
680
|
-
* {@inheritDoc ISerializableInterval.addProperties}
|
|
681
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
682
|
-
*/
|
|
683
|
-
public addProperties(
|
|
684
|
-
newProps: PropertySet,
|
|
685
|
-
collab: boolean = false,
|
|
686
|
-
seq?: number,
|
|
687
|
-
op?: ICombiningOp,
|
|
688
|
-
): PropertySet | undefined {
|
|
689
|
-
this.initializeProperties();
|
|
690
|
-
return this.propertyManager.addProperties(this.properties, newProps, op, seq, collab);
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
/**
|
|
694
|
-
* @returns whether this interval overlaps two numerical positions.
|
|
695
|
-
*/
|
|
696
|
-
public overlapsPos(bstart: number, bend: number) {
|
|
697
|
-
const startPos = this.client.localReferencePositionToPosition(this.start);
|
|
698
|
-
const endPos = this.client.localReferencePositionToPosition(this.end);
|
|
699
|
-
return endPos > bstart && startPos < bend;
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
/**
|
|
703
|
-
* {@inheritDoc IInterval.modify}
|
|
704
|
-
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
705
|
-
*/
|
|
706
|
-
public modify(
|
|
707
|
-
label: string,
|
|
708
|
-
start: number,
|
|
709
|
-
end: number,
|
|
710
|
-
op?: ISequencedDocumentMessage,
|
|
711
|
-
localSeq?: number,
|
|
712
|
-
stickiness: IntervalStickiness = IntervalStickiness.END,
|
|
713
|
-
) {
|
|
714
|
-
const getRefType = (baseType: ReferenceType): ReferenceType => {
|
|
715
|
-
let refType = baseType;
|
|
716
|
-
if (op === undefined) {
|
|
717
|
-
refType &= ~ReferenceType.SlideOnRemove;
|
|
718
|
-
refType |= ReferenceType.StayOnRemove;
|
|
719
|
-
}
|
|
720
|
-
return refType;
|
|
721
|
-
};
|
|
722
|
-
|
|
723
|
-
let startRef = this.start;
|
|
724
|
-
if (start !== undefined) {
|
|
725
|
-
startRef = createPositionReference(
|
|
726
|
-
this.client,
|
|
727
|
-
start,
|
|
728
|
-
getRefType(this.start.refType),
|
|
729
|
-
op,
|
|
730
|
-
undefined,
|
|
731
|
-
localSeq,
|
|
732
|
-
startReferenceSlidingPreference(stickiness),
|
|
733
|
-
);
|
|
734
|
-
if (this.start.properties) {
|
|
735
|
-
startRef.addProperties(this.start.properties);
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
let endRef = this.end;
|
|
740
|
-
if (end !== undefined) {
|
|
741
|
-
endRef = createPositionReference(
|
|
742
|
-
this.client,
|
|
743
|
-
end,
|
|
744
|
-
getRefType(this.end.refType),
|
|
745
|
-
op,
|
|
746
|
-
undefined,
|
|
747
|
-
localSeq,
|
|
748
|
-
endReferenceSlidingPreference(stickiness),
|
|
749
|
-
);
|
|
750
|
-
if (this.end.properties) {
|
|
751
|
-
endRef.addProperties(this.end.properties);
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
const newInterval = new SequenceInterval(this.client, startRef, endRef, this.intervalType);
|
|
756
|
-
if (this.properties) {
|
|
757
|
-
newInterval.initializeProperties();
|
|
758
|
-
this.propertyManager.copyTo(
|
|
759
|
-
this.properties,
|
|
760
|
-
newInterval.properties,
|
|
761
|
-
newInterval.propertyManager,
|
|
762
|
-
);
|
|
763
|
-
}
|
|
764
|
-
return newInterval;
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
private initializeProperties(): void {
|
|
768
|
-
if (!this.propertyManager) {
|
|
769
|
-
this.propertyManager = new PropertiesManager();
|
|
770
|
-
}
|
|
771
|
-
if (!this.properties) {
|
|
772
|
-
this.properties = createMap<any>();
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
export function createPositionReferenceFromSegoff(
|
|
778
|
-
client: Client,
|
|
779
|
-
segoff: { segment: ISegment | undefined; offset: number | undefined },
|
|
780
|
-
refType: ReferenceType,
|
|
781
|
-
op?: ISequencedDocumentMessage,
|
|
782
|
-
localSeq?: number,
|
|
783
|
-
fromSnapshot?: boolean,
|
|
784
|
-
slidingPreference?: SlidingPreference,
|
|
785
|
-
): LocalReferencePosition {
|
|
786
|
-
if (segoff.segment) {
|
|
787
|
-
const ref = client.createLocalReferencePosition(
|
|
788
|
-
segoff.segment,
|
|
789
|
-
segoff.offset,
|
|
790
|
-
refType,
|
|
791
|
-
undefined,
|
|
792
|
-
slidingPreference,
|
|
793
|
-
);
|
|
794
|
-
return ref;
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
// Creating references on detached segments is allowed for:
|
|
798
|
-
// - Transient segments
|
|
799
|
-
// - References coming from a remote client (location may have been concurrently removed)
|
|
800
|
-
// - References being rebased to a new sequence number
|
|
801
|
-
// (segment they originally referred to may have been removed with no suitable replacement)
|
|
802
|
-
if (
|
|
803
|
-
!op &&
|
|
804
|
-
!localSeq &&
|
|
805
|
-
!fromSnapshot &&
|
|
806
|
-
!refTypeIncludesFlag(refType, ReferenceType.Transient)
|
|
807
|
-
) {
|
|
808
|
-
throw new UsageError("Non-transient references need segment");
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
return createDetachedLocalReferencePosition(refType);
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
function createPositionReference(
|
|
815
|
-
client: Client,
|
|
816
|
-
pos: number,
|
|
817
|
-
refType: ReferenceType,
|
|
818
|
-
op?: ISequencedDocumentMessage,
|
|
819
|
-
fromSnapshot?: boolean,
|
|
820
|
-
localSeq?: number,
|
|
821
|
-
slidingPreference?: SlidingPreference,
|
|
822
|
-
): LocalReferencePosition {
|
|
823
|
-
let segoff;
|
|
824
|
-
if (op) {
|
|
825
|
-
assert(
|
|
826
|
-
(refType & ReferenceType.SlideOnRemove) !== 0,
|
|
827
|
-
0x2f5 /* op create references must be SlideOnRemove */,
|
|
828
|
-
);
|
|
829
|
-
segoff = client.getContainingSegment(pos, {
|
|
830
|
-
referenceSequenceNumber: op.referenceSequenceNumber,
|
|
831
|
-
clientId: op.clientId,
|
|
832
|
-
});
|
|
833
|
-
segoff = getSlideToSegoff(segoff);
|
|
834
|
-
} else {
|
|
835
|
-
assert(
|
|
836
|
-
(refType & ReferenceType.SlideOnRemove) === 0 || !!fromSnapshot,
|
|
837
|
-
0x2f6 /* SlideOnRemove references must be op created */,
|
|
838
|
-
);
|
|
839
|
-
segoff = client.getContainingSegment(pos, undefined, localSeq);
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
return createPositionReferenceFromSegoff(
|
|
843
|
-
client,
|
|
844
|
-
segoff,
|
|
845
|
-
refType,
|
|
846
|
-
op,
|
|
847
|
-
localSeq,
|
|
848
|
-
fromSnapshot,
|
|
849
|
-
slidingPreference,
|
|
850
|
-
);
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
export function createSequenceInterval(
|
|
854
|
-
label: string,
|
|
855
|
-
start: number,
|
|
856
|
-
end: number,
|
|
857
|
-
client: Client,
|
|
858
|
-
intervalType: IntervalType,
|
|
859
|
-
op?: ISequencedDocumentMessage,
|
|
860
|
-
fromSnapshot?: boolean,
|
|
861
|
-
stickiness: IntervalStickiness = IntervalStickiness.END,
|
|
862
|
-
): SequenceInterval {
|
|
863
|
-
let beginRefType = ReferenceType.RangeBegin;
|
|
864
|
-
let endRefType = ReferenceType.RangeEnd;
|
|
865
|
-
if (intervalType === IntervalType.Transient) {
|
|
866
|
-
beginRefType = ReferenceType.Transient;
|
|
867
|
-
endRefType = ReferenceType.Transient;
|
|
868
|
-
} else {
|
|
869
|
-
if (intervalType === IntervalType.Nest) {
|
|
870
|
-
beginRefType = ReferenceType.NestBegin;
|
|
871
|
-
endRefType = ReferenceType.NestEnd;
|
|
872
|
-
}
|
|
873
|
-
// All non-transient interval references must eventually be SlideOnRemove
|
|
874
|
-
// To ensure eventual consistency, they must start as StayOnRemove when
|
|
875
|
-
// pending (created locally and creation op is not acked)
|
|
876
|
-
if (op || fromSnapshot) {
|
|
877
|
-
beginRefType |= ReferenceType.SlideOnRemove;
|
|
878
|
-
endRefType |= ReferenceType.SlideOnRemove;
|
|
879
|
-
} else {
|
|
880
|
-
beginRefType |= ReferenceType.StayOnRemove;
|
|
881
|
-
endRefType |= ReferenceType.StayOnRemove;
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
const startLref = createPositionReference(
|
|
886
|
-
client,
|
|
887
|
-
start,
|
|
888
|
-
beginRefType,
|
|
889
|
-
op,
|
|
890
|
-
fromSnapshot,
|
|
891
|
-
undefined,
|
|
892
|
-
startReferenceSlidingPreference(stickiness),
|
|
893
|
-
);
|
|
894
|
-
|
|
895
|
-
const endLref = createPositionReference(
|
|
896
|
-
client,
|
|
897
|
-
end,
|
|
898
|
-
endRefType,
|
|
899
|
-
op,
|
|
900
|
-
fromSnapshot,
|
|
901
|
-
undefined,
|
|
902
|
-
endReferenceSlidingPreference(stickiness),
|
|
903
|
-
);
|
|
904
|
-
|
|
905
|
-
const rangeProp = {
|
|
906
|
-
[reservedRangeLabelsKey]: [label],
|
|
907
|
-
};
|
|
908
|
-
startLref.addProperties(rangeProp);
|
|
909
|
-
endLref.addProperties(rangeProp);
|
|
910
|
-
|
|
911
|
-
const ival = new SequenceInterval(
|
|
912
|
-
client,
|
|
913
|
-
startLref,
|
|
914
|
-
endLref,
|
|
915
|
-
intervalType,
|
|
916
|
-
rangeProp,
|
|
917
|
-
stickiness,
|
|
918
|
-
);
|
|
919
|
-
return ival;
|
|
920
|
-
}
|
|
921
|
-
|
|
922
116
|
export function createIntervalIndex() {
|
|
923
117
|
const helpers: IIntervalHelpers<Interval> = {
|
|
924
|
-
compareEnds:
|
|
118
|
+
compareEnds: (a: Interval, b: Interval) => a.end - b.end,
|
|
925
119
|
create: createInterval,
|
|
926
120
|
};
|
|
927
121
|
const lc = new LocalIntervalCollection<Interval>(undefined as any as Client, "", helpers);
|
|
928
122
|
return lc;
|
|
929
123
|
}
|
|
930
124
|
|
|
931
|
-
/**
|
|
932
|
-
* Collection of intervals.
|
|
933
|
-
*
|
|
934
|
-
* Implementers of this interface will typically implement additional APIs to support efficiently querying a collection
|
|
935
|
-
* of intervals in some manner, for example:
|
|
936
|
-
* - "find all intervals with start endpoint between these two points"
|
|
937
|
-
* - "find all intervals which overlap this range"
|
|
938
|
-
* etc.
|
|
939
|
-
*/
|
|
940
|
-
export interface IntervalIndex<TInterval extends ISerializableInterval> {
|
|
941
|
-
/**
|
|
942
|
-
* Adds an interval to the index.
|
|
943
|
-
* @remarks - Application code should never need to invoke this method on their index for production scenarios:
|
|
944
|
-
* Fluid handles adding and removing intervals from an index in response to sequence or interval changes.
|
|
945
|
-
*/
|
|
946
|
-
add(interval: TInterval): void;
|
|
947
|
-
|
|
948
|
-
/**
|
|
949
|
-
* Removes an interval from the index.
|
|
950
|
-
* @remarks - Application code should never need to invoke this method on their index for production scenarios:
|
|
951
|
-
* Fluid handles adding and removing intervals from an index in response to sequence or interval changes.
|
|
952
|
-
*/
|
|
953
|
-
remove(interval: TInterval): void;
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
class IdIntervalIndex<TInterval extends ISerializableInterval>
|
|
957
|
-
implements IntervalIndex<TInterval>, Iterable<TInterval>
|
|
958
|
-
{
|
|
959
|
-
private readonly intervalIdMap: Map<string, TInterval> = new Map();
|
|
960
|
-
|
|
961
|
-
public add(interval: TInterval) {
|
|
962
|
-
const id = interval.getIntervalId();
|
|
963
|
-
assert(
|
|
964
|
-
id !== undefined,
|
|
965
|
-
0x2c0 /* "ID must be created before adding interval to collection" */,
|
|
966
|
-
);
|
|
967
|
-
// Make the ID immutable.
|
|
968
|
-
Object.defineProperty(interval.properties, reservedIntervalIdKey, {
|
|
969
|
-
configurable: false,
|
|
970
|
-
enumerable: true,
|
|
971
|
-
writable: false,
|
|
972
|
-
});
|
|
973
|
-
this.intervalIdMap.set(id, interval);
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
public remove(interval: TInterval) {
|
|
977
|
-
const id = interval.getIntervalId();
|
|
978
|
-
assert(id !== undefined, 0x311 /* expected id to exist on interval */);
|
|
979
|
-
this.intervalIdMap.delete(id);
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
public getIntervalById(id: string) {
|
|
983
|
-
return this.intervalIdMap.get(id);
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
public [Symbol.iterator]() {
|
|
987
|
-
return this.intervalIdMap.values();
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
class EndpointIndex<TInterval extends ISerializableInterval> implements IntervalIndex<TInterval> {
|
|
992
|
-
private readonly endIntervalTree: RedBlackTree<TInterval, TInterval>;
|
|
993
|
-
|
|
994
|
-
constructor(
|
|
995
|
-
private readonly client: Client,
|
|
996
|
-
private readonly helpers: IIntervalHelpers<TInterval>,
|
|
997
|
-
) {
|
|
998
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
999
|
-
this.endIntervalTree = new RedBlackTree<TInterval, TInterval>(helpers.compareEnds);
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
public previousInterval(pos: number) {
|
|
1003
|
-
const transientInterval = this.helpers.create(
|
|
1004
|
-
"transient",
|
|
1005
|
-
pos,
|
|
1006
|
-
pos,
|
|
1007
|
-
this.client,
|
|
1008
|
-
IntervalType.Transient,
|
|
1009
|
-
);
|
|
1010
|
-
const rbNode = this.endIntervalTree.floor(transientInterval);
|
|
1011
|
-
if (rbNode) {
|
|
1012
|
-
return rbNode.data;
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
public nextInterval(pos: number) {
|
|
1017
|
-
const transientInterval = this.helpers.create(
|
|
1018
|
-
"transient",
|
|
1019
|
-
pos,
|
|
1020
|
-
pos,
|
|
1021
|
-
this.client,
|
|
1022
|
-
IntervalType.Transient,
|
|
1023
|
-
);
|
|
1024
|
-
const rbNode = this.endIntervalTree.ceil(transientInterval);
|
|
1025
|
-
if (rbNode) {
|
|
1026
|
-
return rbNode.data;
|
|
1027
|
-
}
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
public add(interval: TInterval): void {
|
|
1031
|
-
this.endIntervalTree.put(interval, interval);
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
public remove(interval: TInterval): void {
|
|
1035
|
-
this.endIntervalTree.remove(interval);
|
|
1036
|
-
}
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
/**
|
|
1040
|
-
* Collection of intervals.
|
|
1041
|
-
*
|
|
1042
|
-
* Provide additional APIs to support efficiently querying a collection of intervals whose endpoints fall within a specified range.
|
|
1043
|
-
*/
|
|
1044
|
-
export interface IEndpointInRangeIndex<TInterval extends ISerializableInterval>
|
|
1045
|
-
extends IntervalIndex<TInterval> {
|
|
1046
|
-
/**
|
|
1047
|
-
* @returns an array of all intervals contained in this collection whose endpoints locate in the range [start, end] (includes both ends)
|
|
1048
|
-
*/
|
|
1049
|
-
findIntervalsWithEndpointInRange(start: number, end: number);
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
/**
|
|
1053
|
-
* Collection of intervals.
|
|
1054
|
-
*
|
|
1055
|
-
* Provide additional APIs to support efficiently querying a collection of intervals whose startpoints fall within a specified range.
|
|
1056
|
-
*/
|
|
1057
|
-
export interface IStartpointInRangeIndex<TInterval extends ISerializableInterval>
|
|
1058
|
-
extends IntervalIndex<TInterval> {
|
|
1059
|
-
/**
|
|
1060
|
-
* @returns an array of all intervals contained in this collection whose startpoints locate in the range [start, end] (includes both ends)
|
|
1061
|
-
*/
|
|
1062
|
-
findIntervalsWithStartpointInRange(start: number, end: number);
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
|
-
/**
|
|
1066
|
-
* Interface for intervals that have comparison override properties.
|
|
1067
|
-
*/
|
|
1068
|
-
const forceCompare = Symbol();
|
|
1069
|
-
|
|
1070
|
-
interface HasComparisonOverride {
|
|
1071
|
-
[forceCompare]: number;
|
|
1072
|
-
}
|
|
1073
|
-
|
|
1074
|
-
/**
|
|
1075
|
-
* Compares two objects based on their comparison override properties.
|
|
1076
|
-
* @returns A number indicating the order of the intervals (negative for a is lower than b, 0 for tie, positive for a is greater than b).
|
|
1077
|
-
*/
|
|
1078
|
-
function compareOverrideables(
|
|
1079
|
-
a: Partial<HasComparisonOverride>,
|
|
1080
|
-
b: Partial<HasComparisonOverride>,
|
|
1081
|
-
): number {
|
|
1082
|
-
const forceCompareA = a[forceCompare] ?? 0;
|
|
1083
|
-
const forceCompareB = b[forceCompare] ?? 0;
|
|
1084
|
-
|
|
1085
|
-
return forceCompareA - forceCompareB;
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
|
-
class EndpointInRangeIndex<TInterval extends ISerializableInterval>
|
|
1089
|
-
implements IEndpointInRangeIndex<TInterval>
|
|
1090
|
-
{
|
|
1091
|
-
private readonly intervalTree;
|
|
1092
|
-
|
|
1093
|
-
constructor(
|
|
1094
|
-
private readonly helpers: IIntervalHelpers<TInterval>,
|
|
1095
|
-
private readonly client: Client,
|
|
1096
|
-
) {
|
|
1097
|
-
this.intervalTree = new RedBlackTree<TInterval, TInterval>((a: TInterval, b: TInterval) => {
|
|
1098
|
-
const compareEndsResult = helpers.compareEnds(a, b);
|
|
1099
|
-
if (compareEndsResult !== 0) {
|
|
1100
|
-
return compareEndsResult;
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
const overrideablesComparison = compareOverrideables(
|
|
1104
|
-
a as Partial<HasComparisonOverride>,
|
|
1105
|
-
b as Partial<HasComparisonOverride>,
|
|
1106
|
-
);
|
|
1107
|
-
if (overrideablesComparison !== 0) {
|
|
1108
|
-
return overrideablesComparison;
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
const aId = a.getIntervalId();
|
|
1112
|
-
const bId = b.getIntervalId();
|
|
1113
|
-
if (aId !== undefined && bId !== undefined) {
|
|
1114
|
-
return aId.localeCompare(bId);
|
|
1115
|
-
}
|
|
1116
|
-
return 0;
|
|
1117
|
-
});
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
public add(interval: TInterval): void {
|
|
1121
|
-
this.intervalTree.put(interval, interval);
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
public remove(interval: TInterval): void {
|
|
1125
|
-
this.intervalTree.remove(interval);
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
public findIntervalsWithEndpointInRange(start: number, end: number) {
|
|
1129
|
-
if (start <= 0 || start > end || this.intervalTree.isEmpty()) {
|
|
1130
|
-
return [];
|
|
1131
|
-
}
|
|
1132
|
-
const results: TInterval[] = [];
|
|
1133
|
-
const action: PropertyAction<TInterval, TInterval> = (node) => {
|
|
1134
|
-
results.push(node.data);
|
|
1135
|
-
return true;
|
|
1136
|
-
};
|
|
1137
|
-
|
|
1138
|
-
const transientStartInterval = this.helpers.create(
|
|
1139
|
-
"transient",
|
|
1140
|
-
start,
|
|
1141
|
-
start,
|
|
1142
|
-
this.client,
|
|
1143
|
-
IntervalType.Transient,
|
|
1144
|
-
);
|
|
1145
|
-
|
|
1146
|
-
const transientEndInterval = this.helpers.create(
|
|
1147
|
-
"transient",
|
|
1148
|
-
end,
|
|
1149
|
-
end,
|
|
1150
|
-
this.client,
|
|
1151
|
-
IntervalType.Transient,
|
|
1152
|
-
);
|
|
1153
|
-
|
|
1154
|
-
// Add comparison overrides to the transient intervals
|
|
1155
|
-
(transientStartInterval as Partial<HasComparisonOverride>)[forceCompare] = -1;
|
|
1156
|
-
(transientEndInterval as Partial<HasComparisonOverride>)[forceCompare] = 1;
|
|
1157
|
-
|
|
1158
|
-
this.intervalTree.mapRange(action, results, transientStartInterval, transientEndInterval);
|
|
1159
|
-
return results;
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
class StartpointInRangeIndex<TInterval extends ISerializableInterval>
|
|
1164
|
-
implements IStartpointInRangeIndex<TInterval>
|
|
1165
|
-
{
|
|
1166
|
-
private readonly intervalTree;
|
|
1167
|
-
|
|
1168
|
-
constructor(
|
|
1169
|
-
private readonly helpers: IIntervalHelpers<TInterval>,
|
|
1170
|
-
private readonly client: Client,
|
|
1171
|
-
) {
|
|
1172
|
-
this.intervalTree = new RedBlackTree<TInterval, TInterval>((a: TInterval, b: TInterval) => {
|
|
1173
|
-
assert(
|
|
1174
|
-
typeof helpers.compareStarts === "function",
|
|
1175
|
-
0x6d1 /* compareStarts does not exist in the helpers */,
|
|
1176
|
-
);
|
|
1177
|
-
|
|
1178
|
-
const compareStartsResult = helpers.compareStarts(a, b);
|
|
1179
|
-
if (compareStartsResult !== 0) {
|
|
1180
|
-
return compareStartsResult;
|
|
1181
|
-
}
|
|
1182
|
-
|
|
1183
|
-
const overrideablesComparison = compareOverrideables(
|
|
1184
|
-
a as Partial<HasComparisonOverride>,
|
|
1185
|
-
b as Partial<HasComparisonOverride>,
|
|
1186
|
-
);
|
|
1187
|
-
if (overrideablesComparison !== 0) {
|
|
1188
|
-
return overrideablesComparison;
|
|
1189
|
-
}
|
|
1190
|
-
const aId = a.getIntervalId();
|
|
1191
|
-
const bId = b.getIntervalId();
|
|
1192
|
-
if (aId !== undefined && bId !== undefined) {
|
|
1193
|
-
return aId.localeCompare(bId);
|
|
1194
|
-
}
|
|
1195
|
-
return 0;
|
|
1196
|
-
});
|
|
1197
|
-
}
|
|
1198
|
-
|
|
1199
|
-
public add(interval: TInterval): void {
|
|
1200
|
-
this.intervalTree.put(interval, interval);
|
|
1201
|
-
}
|
|
1202
|
-
|
|
1203
|
-
public remove(interval: TInterval): void {
|
|
1204
|
-
this.intervalTree.remove(interval);
|
|
1205
|
-
}
|
|
1206
|
-
|
|
1207
|
-
public findIntervalsWithStartpointInRange(start: number, end: number) {
|
|
1208
|
-
if (start <= 0 || start > end || this.intervalTree.isEmpty()) {
|
|
1209
|
-
return [];
|
|
1210
|
-
}
|
|
1211
|
-
const results: TInterval[] = [];
|
|
1212
|
-
const action: PropertyAction<TInterval, TInterval> = (node) => {
|
|
1213
|
-
results.push(node.data);
|
|
1214
|
-
return true;
|
|
1215
|
-
};
|
|
1216
|
-
|
|
1217
|
-
const transientStartInterval = this.helpers.create(
|
|
1218
|
-
"transient",
|
|
1219
|
-
start,
|
|
1220
|
-
start,
|
|
1221
|
-
this.client,
|
|
1222
|
-
IntervalType.Transient,
|
|
1223
|
-
);
|
|
1224
|
-
|
|
1225
|
-
const transientEndInterval = this.helpers.create(
|
|
1226
|
-
"transient",
|
|
1227
|
-
end,
|
|
1228
|
-
end,
|
|
1229
|
-
this.client,
|
|
1230
|
-
IntervalType.Transient,
|
|
1231
|
-
);
|
|
1232
|
-
|
|
1233
|
-
// Add comparison overrides to the transient intervals
|
|
1234
|
-
(transientStartInterval as Partial<HasComparisonOverride>)[forceCompare] = -1;
|
|
1235
|
-
(transientEndInterval as Partial<HasComparisonOverride>)[forceCompare] = 1;
|
|
1236
|
-
|
|
1237
|
-
this.intervalTree.mapRange(action, results, transientStartInterval, transientEndInterval);
|
|
1238
|
-
return results;
|
|
1239
|
-
}
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
export function createEndpointInRangeIndex<TInterval extends ISerializableInterval>(
|
|
1243
|
-
helpers: IIntervalHelpers<TInterval>,
|
|
1244
|
-
client: Client,
|
|
1245
|
-
): IEndpointInRangeIndex<TInterval> {
|
|
1246
|
-
return new EndpointInRangeIndex<TInterval>(helpers, client);
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
export function createStartpointInRangeIndex<TInterval extends ISerializableInterval>(
|
|
1250
|
-
helpers: IIntervalHelpers<TInterval>,
|
|
1251
|
-
client: Client,
|
|
1252
|
-
): IStartpointInRangeIndex<TInterval> {
|
|
1253
|
-
return new StartpointInRangeIndex<TInterval>(helpers, client);
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
125
|
export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
|
|
1257
126
|
private static readonly legacyIdPrefix = "legacy";
|
|
1258
127
|
public readonly overlappingIntervalsIndex: IOverlappingIntervalsIndex<TInterval>;
|
|
1259
|
-
public readonly idIntervalIndex:
|
|
1260
|
-
public readonly endIntervalIndex:
|
|
128
|
+
public readonly idIntervalIndex: IIdIntervalIndex<TInterval>;
|
|
129
|
+
public readonly endIntervalIndex: IEndpointIndex<TInterval>;
|
|
1261
130
|
private readonly indexes: Set<IntervalIndex<TInterval>>;
|
|
1262
131
|
|
|
1263
132
|
constructor(
|
|
@@ -1271,8 +140,8 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
|
|
|
1271
140
|
) => void,
|
|
1272
141
|
) {
|
|
1273
142
|
this.overlappingIntervalsIndex = createOverlappingIntervalsIndex(client, helpers);
|
|
1274
|
-
this.idIntervalIndex =
|
|
1275
|
-
this.endIntervalIndex =
|
|
143
|
+
this.idIntervalIndex = createIdIntervalIndex<TInterval>();
|
|
144
|
+
this.endIntervalIndex = createEndpointIndex(client, helpers);
|
|
1276
145
|
this.indexes = new Set([
|
|
1277
146
|
this.overlappingIntervalsIndex,
|
|
1278
147
|
this.idIntervalIndex,
|
|
@@ -1488,24 +357,6 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
|
|
|
1488
357
|
}
|
|
1489
358
|
}
|
|
1490
359
|
|
|
1491
|
-
export const compareSequenceIntervalEnds = (a: SequenceInterval, b: SequenceInterval): number =>
|
|
1492
|
-
compareReferencePositions(a.end, b.end);
|
|
1493
|
-
|
|
1494
|
-
export const compareSequenceIntervalStarts = (a: SequenceInterval, b: SequenceInterval): number =>
|
|
1495
|
-
compareReferencePositions(a.start, b.start);
|
|
1496
|
-
|
|
1497
|
-
export const sequenceIntervalHelpers: IIntervalHelpers<SequenceInterval> = {
|
|
1498
|
-
compareEnds: compareSequenceIntervalEnds,
|
|
1499
|
-
compareStarts: compareSequenceIntervalStarts,
|
|
1500
|
-
create: createSequenceInterval,
|
|
1501
|
-
};
|
|
1502
|
-
|
|
1503
|
-
export const intervalHelpers: IIntervalHelpers<Interval> = {
|
|
1504
|
-
compareEnds: (a: Interval, b: Interval) => a.end - b.end,
|
|
1505
|
-
compareStarts: (a: Interval, b: Interval) => a.start - b.start,
|
|
1506
|
-
create: createInterval,
|
|
1507
|
-
};
|
|
1508
|
-
|
|
1509
360
|
class SequenceIntervalCollectionFactory
|
|
1510
361
|
implements IValueFactory<IntervalCollection<SequenceInterval>>
|
|
1511
362
|
{
|
|
@@ -1553,26 +404,6 @@ export class SequenceIntervalCollectionValueType
|
|
|
1553
404
|
private static readonly _ops = makeOpsMap<SequenceInterval>();
|
|
1554
405
|
}
|
|
1555
406
|
|
|
1556
|
-
const compareIntervalEnds = (a: Interval, b: Interval) => a.end - b.end;
|
|
1557
|
-
|
|
1558
|
-
function createInterval(
|
|
1559
|
-
label: string,
|
|
1560
|
-
start: number,
|
|
1561
|
-
end: number,
|
|
1562
|
-
client: Client,
|
|
1563
|
-
intervalType?: IntervalType,
|
|
1564
|
-
op?: ISequencedDocumentMessage,
|
|
1565
|
-
fromSnapshot?: boolean,
|
|
1566
|
-
): Interval {
|
|
1567
|
-
const rangeProp: PropertySet = {};
|
|
1568
|
-
|
|
1569
|
-
if (label && label.length > 0) {
|
|
1570
|
-
rangeProp[reservedRangeLabelsKey] = [label];
|
|
1571
|
-
}
|
|
1572
|
-
|
|
1573
|
-
return new Interval(start, end, rangeProp);
|
|
1574
|
-
}
|
|
1575
|
-
|
|
1576
407
|
class IntervalCollectionFactory implements IValueFactory<IntervalCollection<Interval>> {
|
|
1577
408
|
public load(
|
|
1578
409
|
emitter: IValueOpEmitter,
|
|
@@ -1580,7 +411,7 @@ class IntervalCollectionFactory implements IValueFactory<IntervalCollection<Inte
|
|
|
1580
411
|
options?: Partial<SequenceOptions>,
|
|
1581
412
|
): IntervalCollection<Interval> {
|
|
1582
413
|
const helpers: IIntervalHelpers<Interval> = {
|
|
1583
|
-
compareEnds:
|
|
414
|
+
compareEnds: (a: Interval, b: Interval) => a.end - b.end,
|
|
1584
415
|
create: createInterval,
|
|
1585
416
|
};
|
|
1586
417
|
const collection = new IntervalCollection<Interval>(helpers, false, emitter, raw, options);
|
|
@@ -1847,21 +678,29 @@ export interface IIntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1847
678
|
|
|
1848
679
|
/**
|
|
1849
680
|
* @returns a forward iterator over all intervals in this collection with start point equal to `startPosition`.
|
|
681
|
+
*
|
|
682
|
+
* @deprecated - The sequence order of collection order will not be supported
|
|
1850
683
|
*/
|
|
1851
684
|
CreateForwardIteratorWithStartPosition(startPosition: number): Iterator<TInterval>;
|
|
1852
685
|
|
|
1853
686
|
/**
|
|
1854
687
|
* @returns a backward iterator over all intervals in this collection with start point equal to `startPosition`.
|
|
688
|
+
*
|
|
689
|
+
* @deprecated - The sequence order of collection order will not be supported
|
|
1855
690
|
*/
|
|
1856
691
|
CreateBackwardIteratorWithStartPosition(startPosition: number): Iterator<TInterval>;
|
|
1857
692
|
|
|
1858
693
|
/**
|
|
1859
694
|
* @returns a forward iterator over all intervals in this collection with end point equal to `endPosition`.
|
|
695
|
+
*
|
|
696
|
+
* @deprecated - The sequence order of collection order will not be supported
|
|
1860
697
|
*/
|
|
1861
698
|
CreateForwardIteratorWithEndPosition(endPosition: number): Iterator<TInterval>;
|
|
1862
699
|
|
|
1863
700
|
/**
|
|
1864
701
|
* @returns a backward iterator over all intervals in this collection with end point equal to `endPosition`.
|
|
702
|
+
*
|
|
703
|
+
* @deprecated - The sequence order of collection order will not be supported
|
|
1865
704
|
*/
|
|
1866
705
|
CreateBackwardIteratorWithEndPosition(endPosition: number): Iterator<TInterval>;
|
|
1867
706
|
|
|
@@ -1872,6 +711,9 @@ export interface IIntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1872
711
|
* @param iteratesForward - whether or not iteration should be in the forward direction
|
|
1873
712
|
* @param start - If provided, only match intervals whose start point is equal to `start`.
|
|
1874
713
|
* @param end - If provided, only match intervals whose end point is equal to `end`.
|
|
714
|
+
*
|
|
715
|
+
* @deprecated - This API will be deprecated as its functionality will be moved to the `OverlappingIntervalsIndex`.
|
|
716
|
+
* We would like the user to attach the index to the collection on their own.
|
|
1875
717
|
*/
|
|
1876
718
|
gatherIterationResults(
|
|
1877
719
|
results: TInterval[],
|
|
@@ -1883,6 +725,9 @@ export interface IIntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1883
725
|
/**
|
|
1884
726
|
* @returns an array of all intervals in this collection that overlap with the interval
|
|
1885
727
|
* `[startPosition, endPosition]`.
|
|
728
|
+
*
|
|
729
|
+
* @deprecated - This API will be deprecated as its functionality will be moved to the `OverlappingIntervalsIndex`.
|
|
730
|
+
* We would like the user to attach the index to the collection on their own.
|
|
1886
731
|
*/
|
|
1887
732
|
findOverlappingIntervals(startPosition: number, endPosition: number): TInterval[];
|
|
1888
733
|
|
|
@@ -1891,8 +736,16 @@ export interface IIntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1891
736
|
*/
|
|
1892
737
|
map(fn: (interval: TInterval) => void): void;
|
|
1893
738
|
|
|
739
|
+
/**
|
|
740
|
+
* @deprecated - This API will be deprecated as its functionality will be moved to the `EndpointIndex`.
|
|
741
|
+
* We would like the user to attach the index to the collection on their own.
|
|
742
|
+
*/
|
|
1894
743
|
previousInterval(pos: number): TInterval | undefined;
|
|
1895
744
|
|
|
745
|
+
/**
|
|
746
|
+
* @deprecated - This API will be deprecated as its functionality will be moved to the `EndpointIndex`.
|
|
747
|
+
* We would like the user to attach the index to the collection on their own.
|
|
748
|
+
*/
|
|
1896
749
|
nextInterval(pos: number): TInterval | undefined;
|
|
1897
750
|
}
|
|
1898
751
|
|
|
@@ -2128,7 +981,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
2128
981
|
/**
|
|
2129
982
|
* {@inheritdoc IIntervalCollection.getIntervalById}
|
|
2130
983
|
*/
|
|
2131
|
-
public getIntervalById(id: string) {
|
|
984
|
+
public getIntervalById(id: string): TInterval | undefined {
|
|
2132
985
|
if (!this.localCollection) {
|
|
2133
986
|
throw new LoggingError("attach must be called before accessing intervals");
|
|
2134
987
|
}
|
|
@@ -2216,7 +1069,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
2216
1069
|
/**
|
|
2217
1070
|
* {@inheritdoc IIntervalCollection.removeIntervalById}
|
|
2218
1071
|
*/
|
|
2219
|
-
public removeIntervalById(id: string) {
|
|
1072
|
+
public removeIntervalById(id: string): TInterval | undefined {
|
|
2220
1073
|
if (!this.localCollection) {
|
|
2221
1074
|
throw new LoggingError("Attach must be called before accessing intervals");
|
|
2222
1075
|
}
|
|
@@ -2755,6 +1608,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
2755
1608
|
|
|
2756
1609
|
/**
|
|
2757
1610
|
* {@inheritdoc IIntervalCollection.CreateForwardIteratorWithStartPosition}
|
|
1611
|
+
*
|
|
1612
|
+
* @deprecated - The sequence order of collection order will not be supported
|
|
2758
1613
|
*/
|
|
2759
1614
|
public CreateForwardIteratorWithStartPosition(
|
|
2760
1615
|
startPosition: number,
|
|
@@ -2765,6 +1620,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
2765
1620
|
|
|
2766
1621
|
/**
|
|
2767
1622
|
* {@inheritdoc IIntervalCollection.CreateBackwardIteratorWithStartPosition}
|
|
1623
|
+
*
|
|
1624
|
+
* @deprecated - The sequence order of collection order will not be supported
|
|
2768
1625
|
*/
|
|
2769
1626
|
public CreateBackwardIteratorWithStartPosition(
|
|
2770
1627
|
startPosition: number,
|
|
@@ -2775,6 +1632,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
2775
1632
|
|
|
2776
1633
|
/**
|
|
2777
1634
|
* {@inheritdoc IIntervalCollection.CreateForwardIteratorWithEndPosition}
|
|
1635
|
+
*
|
|
1636
|
+
* @deprecated - The sequence order of collection order will not be supported
|
|
2778
1637
|
*/
|
|
2779
1638
|
public CreateForwardIteratorWithEndPosition(
|
|
2780
1639
|
endPosition: number,
|
|
@@ -2790,6 +1649,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
2790
1649
|
|
|
2791
1650
|
/**
|
|
2792
1651
|
* {@inheritdoc IIntervalCollection.CreateBackwardIteratorWithEndPosition}
|
|
1652
|
+
*
|
|
1653
|
+
* @deprecated - The sequence order of collection order will not be supported
|
|
2793
1654
|
*/
|
|
2794
1655
|
public CreateBackwardIteratorWithEndPosition(
|
|
2795
1656
|
endPosition: number,
|
|
@@ -2805,6 +1666,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
2805
1666
|
|
|
2806
1667
|
/**
|
|
2807
1668
|
* {@inheritdoc IIntervalCollection.gatherIterationResults}
|
|
1669
|
+
* @deprecated - This API will be deprecated as its functionality will be moved to the `OverlappingIntervalsIndex`.
|
|
1670
|
+
* We would like the user to attach the index to the collection on their own.
|
|
2808
1671
|
*/
|
|
2809
1672
|
public gatherIterationResults(
|
|
2810
1673
|
results: TInterval[],
|
|
@@ -2826,6 +1689,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
2826
1689
|
|
|
2827
1690
|
/**
|
|
2828
1691
|
* {@inheritdoc IIntervalCollection.findOverlappingIntervals}
|
|
1692
|
+
* @deprecated - This API will be deprecated as its functionality will be moved to the `OverlappingIntervalsIndex`.
|
|
1693
|
+
* We would like the user to attach the index to the collection on their own.
|
|
2829
1694
|
*/
|
|
2830
1695
|
public findOverlappingIntervals(startPosition: number, endPosition: number): TInterval[] {
|
|
2831
1696
|
if (!this.localCollection) {
|
|
@@ -2853,6 +1718,9 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
2853
1718
|
|
|
2854
1719
|
/**
|
|
2855
1720
|
* {@inheritdoc IIntervalCollection.previousInterval}
|
|
1721
|
+
*
|
|
1722
|
+
* @deprecated - This API will be deprecated as its functionality will be moved to the `EndpointIndex`.
|
|
1723
|
+
* We would like the user to attach the index to the collection on their own.
|
|
2856
1724
|
*/
|
|
2857
1725
|
public previousInterval(pos: number): TInterval | undefined {
|
|
2858
1726
|
if (!this.localCollection) {
|
|
@@ -2864,6 +1732,9 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
2864
1732
|
|
|
2865
1733
|
/**
|
|
2866
1734
|
* {@inheritdoc IIntervalCollection.nextInterval}
|
|
1735
|
+
*
|
|
1736
|
+
* @deprecated - This API will be deprecated as its functionality will be moved to the `EndpointIndex`.
|
|
1737
|
+
* We would like the user to attach the index to the collection on their own.
|
|
2867
1738
|
*/
|
|
2868
1739
|
public nextInterval(pos: number): TInterval | undefined {
|
|
2869
1740
|
if (!this.localCollection) {
|