@y/y 14.0.0-16 → 14.0.0-17

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.
Files changed (68) hide show
  1. package/dist/{index-DyTeTfmj.js → index-BV-j5wdP.js} +2 -2
  2. package/dist/{index-R7GxO-36.js.map → index-BV-j5wdP.js.map} +1 -1
  3. package/dist/{internals.mjs → internals.js} +1 -1
  4. package/dist/internals.js.map +1 -0
  5. package/dist/{testHelper.mjs → testHelper.js} +2 -2
  6. package/dist/testHelper.js.map +1 -0
  7. package/dist/{yjs.mjs → yjs.js} +2 -2
  8. package/dist/yjs.js.map +1 -0
  9. package/package.json +8 -17
  10. package/dist/Skip-j0kX7pdq.js +0 -12173
  11. package/dist/Skip-j0kX7pdq.js.map +0 -1
  12. package/dist/index-DyTeTfmj.js.map +0 -1
  13. package/dist/index-R7GxO-36.js +0 -165
  14. package/dist/internals.cjs +0 -286
  15. package/dist/internals.cjs.map +0 -1
  16. package/dist/internals.mjs.map +0 -1
  17. package/dist/testHelper.cjs +0 -780
  18. package/dist/testHelper.cjs.map +0 -1
  19. package/dist/testHelper.mjs.map +0 -1
  20. package/dist/yjs.cjs +0 -151
  21. package/dist/yjs.cjs.map +0 -1
  22. package/dist/yjs.mjs.map +0 -1
  23. package/src/index.js +0 -153
  24. package/src/internals.js +0 -44
  25. package/src/structs/AbstractStruct.js +0 -59
  26. package/src/structs/ContentAny.js +0 -115
  27. package/src/structs/ContentBinary.js +0 -93
  28. package/src/structs/ContentDeleted.js +0 -101
  29. package/src/structs/ContentDoc.js +0 -141
  30. package/src/structs/ContentEmbed.js +0 -98
  31. package/src/structs/ContentFormat.js +0 -105
  32. package/src/structs/ContentJSON.js +0 -119
  33. package/src/structs/ContentString.js +0 -113
  34. package/src/structs/ContentType.js +0 -176
  35. package/src/structs/GC.js +0 -80
  36. package/src/structs/Item.js +0 -845
  37. package/src/structs/Skip.js +0 -75
  38. package/src/types/AbstractType.js +0 -1434
  39. package/src/types/YArray.js +0 -270
  40. package/src/types/YMap.js +0 -244
  41. package/src/types/YText.js +0 -934
  42. package/src/types/YXmlElement.js +0 -227
  43. package/src/types/YXmlFragment.js +0 -266
  44. package/src/types/YXmlHook.js +0 -68
  45. package/src/types/YXmlText.js +0 -66
  46. package/src/utils/AbstractConnector.js +0 -25
  47. package/src/utils/AttributionManager.js +0 -619
  48. package/src/utils/Doc.js +0 -372
  49. package/src/utils/EventHandler.js +0 -87
  50. package/src/utils/ID.js +0 -89
  51. package/src/utils/IdMap.js +0 -629
  52. package/src/utils/IdSet.js +0 -823
  53. package/src/utils/RelativePosition.js +0 -352
  54. package/src/utils/Snapshot.js +0 -220
  55. package/src/utils/StructSet.js +0 -137
  56. package/src/utils/StructStore.js +0 -289
  57. package/src/utils/Transaction.js +0 -489
  58. package/src/utils/UndoManager.js +0 -391
  59. package/src/utils/UpdateDecoder.js +0 -281
  60. package/src/utils/UpdateEncoder.js +0 -320
  61. package/src/utils/YEvent.js +0 -216
  62. package/src/utils/delta-helpers.js +0 -54
  63. package/src/utils/encoding.js +0 -623
  64. package/src/utils/isParentOf.js +0 -21
  65. package/src/utils/logging.js +0 -21
  66. package/src/utils/types.js +0 -28
  67. package/src/utils/updates.js +0 -715
  68. package/tests/testHelper.js +0 -600
@@ -1,629 +0,0 @@
1
- import {
2
- _diffSet,
3
- findIndexInIdRanges,
4
- findRangeStartInIdRanges,
5
- _deleteRangeFromIdSet,
6
- DSDecoderV1, DSDecoderV2, IdSetEncoderV1, IdSetEncoderV2, IdSet, ID, // eslint-disable-line
7
- _insertIntoIdSet,
8
- _intersectSets
9
- } from '../internals.js'
10
-
11
- import * as array from 'lib0/array'
12
- import * as map from 'lib0/map'
13
- import * as encoding from 'lib0/encoding'
14
- import * as decoding from 'lib0/decoding'
15
- import * as buf from 'lib0/buffer'
16
- import * as rabin from 'lib0/hash/rabin'
17
-
18
- /**
19
- * @todo rename this to `Attribute`
20
- * @template V
21
- */
22
- export class AttributionItem {
23
- /**
24
- * @param {string} name
25
- * @param {V} val
26
- */
27
- constructor (name, val) {
28
- this.name = name
29
- this.val = val
30
- }
31
-
32
- hash () {
33
- const encoder = encoding.createEncoder()
34
- encoding.writeVarString(encoder, this.name)
35
- encoding.writeAny(encoder, /** @type {any} */ (this.val))
36
- return buf.toBase64(rabin.fingerprint(rabin.StandardIrreducible128, encoding.toUint8Array(encoder)))
37
- }
38
- }
39
-
40
- /**
41
- * @param {AttributionItem<any>} attr
42
- */
43
- const _hashAttribution = attr => {
44
- const encoder = encoding.createEncoder()
45
- encoding.writeVarString(encoder, attr.name)
46
- encoding.writeAny(encoder, attr.val)
47
- return buf.toBase64(rabin.fingerprint(rabin.StandardIrreducible128, encoding.toUint8Array(encoder)))
48
- }
49
-
50
- /**
51
- * @todo rename this to `createAttribute`
52
- * @template V
53
- * @param {string} name
54
- * @param {V} val
55
- * @return {AttributionItem<V>}
56
- */
57
- export const createAttributionItem = (name, val) => new AttributionItem(name, val)
58
-
59
- /**
60
- * @template T
61
- * @param {Array<T>} attrs
62
- * @param {T} attr
63
- *
64
- */
65
- const idmapAttrsHas = (attrs, attr) => attrs.find(a => a === attr)
66
-
67
- /**
68
- * @template T
69
- * @param {Array<T>} a
70
- * @param {Array<T>} b
71
- */
72
- export const idmapAttrsEqual = (a, b) => a.length === b.length && a.every(v => idmapAttrsHas(b, v))
73
-
74
- /**
75
- * @template T
76
- * @param {Array<T>} a
77
- * @param {Array<T>} b
78
- */
79
- const idmapAttrRangeJoin = (a, b) => a.concat(b.filter(attr => !idmapAttrsHas(a, attr)))
80
-
81
- /**
82
- * @template Attrs
83
- */
84
- export class AttrRange {
85
- /**
86
- * @param {number} clock
87
- * @param {number} len
88
- * @param {Array<AttributionItem<Attrs>>} attrs
89
- */
90
- constructor (clock, len, attrs) {
91
- /**
92
- * @readonly
93
- */
94
- this.clock = clock
95
- /**
96
- * @readonly
97
- */
98
- this.len = len
99
- /**
100
- * @readonly
101
- */
102
- this.attrs = attrs
103
- }
104
-
105
- /**
106
- * @param {number} clock
107
- * @param {number} len
108
- */
109
- copyWith (clock, len) {
110
- return new AttrRange(clock, len, this.attrs)
111
- }
112
- }
113
-
114
- /**
115
- * @template Attrs
116
- * @typedef {{ clock: number, len: number, attrs: Array<AttributionItem<Attrs>>? }} MaybeAttrRange
117
- */
118
-
119
- /**
120
- * @template Attrs
121
- *
122
- * @param {number} clock
123
- * @param {number} len
124
- * @param {Array<AttributionItem<Attrs>>?} attrs
125
- * @return {MaybeAttrRange<Attrs>}
126
- */
127
- export const createMaybeAttrRange = (clock, len, attrs) => new AttrRange(clock, len, /** @type {any} */ (attrs))
128
-
129
- /**
130
- * Whenever this is instantiated, it must receive a fresh array of ops, not something copied.
131
- *
132
- * @template Attrs
133
- */
134
- export class AttrRanges {
135
- /**
136
- * @param {Array<AttrRange<Attrs>>} ids
137
- */
138
- constructor (ids) {
139
- this.sorted = false
140
- /**
141
- * @private
142
- */
143
- this._ids = ids
144
- }
145
-
146
- copy () {
147
- return new AttrRanges(this._ids.slice())
148
- }
149
-
150
- /**
151
- * @param {number} clock
152
- * @param {number} length
153
- * @param {Array<AttributionItem<Attrs>>} attrs
154
- */
155
- add (clock, length, attrs) {
156
- if (length === 0) return
157
- this.sorted = false
158
- this._ids.push(new AttrRange(clock, length, attrs))
159
- }
160
-
161
- /**
162
- * Return the list of id ranges, sorted and merged.
163
- */
164
- getIds () {
165
- const ids = this._ids
166
- if (!this.sorted) {
167
- this.sorted = true
168
- ids.sort((a, b) => a.clock - b.clock)
169
- /**
170
- * algorithm thoughts:
171
- * - sort (by clock AND by length), bigger length is to the right (or not, we can't make
172
- * assumptions abouth length after long length has been split)
173
- * -- maybe better: sort by clock+length. Then split items from right to left. This way, items are always
174
- * in the right order. But I also need to swap if left items is smaller after split
175
- * --- thought: there is no way to go around swapping. Unless, for each item from left to
176
- * right, when I have to split because one of the look-ahead items is overlapping, i split
177
- * it and merge the attributes into the following ones (that I also need to split). Best is
178
- * probably left to right with lookahead.
179
- * - left to right, split overlapping items so that we can make the assumption that either an
180
- * item is overlapping with the next 1-on-1 or it is not overlapping at all (when splitting,
181
- * we can already incorporate the attributes)
182
- * -- better: for each item, go left to right and add own attributes to overlapping items.
183
- * Split them if necessary. After split, i must insert the retainer at a valid position.
184
- * - merge items if neighbor has same attributes
185
- */
186
- for (let i = 0; i < ids.length - 1;) {
187
- const range = ids[i]
188
- const nextRange = ids[i + 1]
189
- // find out how to split range. it must match with next range.
190
- // 1) we have space. Split if necessary.
191
- // 2) concat attributes in range to the next range. Split range and splice the remainder at
192
- // the correct position.
193
- if (range.clock < nextRange.clock) { // might need to split range
194
- if (range.clock + range.len > nextRange.clock) {
195
- // is overlapping
196
- const diff = nextRange.clock - range.clock
197
- ids[i] = new AttrRange(range.clock, diff, range.attrs)
198
- ids.splice(i + 1, 0, new AttrRange(nextRange.clock, range.len - diff, range.attrs))
199
- }
200
- i++
201
- continue
202
- }
203
- // now we know that range.clock === nextRange.clock
204
- // merge range with nextRange
205
- const largerRange = range.len > nextRange.len ? range : nextRange
206
- const smallerLen = range.len < nextRange.len ? range.len : nextRange.len
207
- ids[i] = new AttrRange(range.clock, smallerLen, idmapAttrRangeJoin(range.attrs, nextRange.attrs))
208
- if (range.len === nextRange.len) {
209
- ids.splice(i + 1, 1)
210
- } else {
211
- ids[i + 1] = new AttrRange(range.clock + smallerLen, largerRange.len - smallerLen, largerRange.attrs)
212
- array.bubblesortItem(ids, i + 1, (a, b) => a.clock - b.clock)
213
- }
214
- if (smallerLen === 0) i++
215
- }
216
- while (ids.length > 0 && ids[0].len === 0) {
217
- ids.splice(0, 1)
218
- }
219
- // merge items without filtering or splicing the array.
220
- // i is the current pointer
221
- // j refers to the current insert position for the pointed item
222
- // try to merge dels[i] into dels[j-1] or set dels[j]=dels[i]
223
- let i, j
224
- for (i = 1, j = 1; i < ids.length; i++) {
225
- const left = ids[j - 1]
226
- const right = ids[i]
227
- if (left.clock + left.len === right.clock && idmapAttrsEqual(left.attrs, right.attrs)) {
228
- ids[j - 1] = new AttrRange(left.clock, left.len + right.len, left.attrs)
229
- } else if (right.len !== 0) {
230
- if (j < i) {
231
- ids[j] = right
232
- }
233
- j++
234
- }
235
- }
236
- ids.length = ids.length === 0 ? 0 : (ids[j - 1].len === 0 ? j - 1 : j)
237
- }
238
- return ids
239
- }
240
- }
241
-
242
- /**
243
- * Merge multiple idmaps. Ensures that there are no redundant attribution definitions (two
244
- * Attributions that describe the same thing).
245
- *
246
- * @template T
247
- * @param {Array<IdMap<T>>} ams
248
- * @return {IdMap<T>} A fresh IdSet
249
- */
250
- export const mergeIdMaps = ams => {
251
- /**
252
- * Maps attribution to the attribution of the merged idmap.
253
- *
254
- * @type {Map<AttributionItem<any>,AttributionItem<any>>}
255
- */
256
- const attrMapper = new Map()
257
- const merged = createIdMap()
258
- for (let amsI = 0; amsI < ams.length; amsI++) {
259
- ams[amsI].clients.forEach((rangesLeft, client) => {
260
- if (!merged.clients.has(client)) {
261
- // Write all missing keys from current set and all following.
262
- // If merged already contains `client` current ds has already been added.
263
- let ids = rangesLeft.getIds().slice()
264
- for (let i = amsI + 1; i < ams.length; i++) {
265
- const nextIds = ams[i].clients.get(client)
266
- if (nextIds) {
267
- array.appendTo(ids, nextIds.getIds())
268
- }
269
- }
270
- ids = ids.map(id => new AttrRange(id.clock, id.len, id.attrs.map(attr =>
271
- map.setIfUndefined(attrMapper, attr, () =>
272
- _ensureAttrs(merged, [attr])[0]
273
- )
274
- )))
275
- merged.clients.set(client, new AttrRanges(ids))
276
- }
277
- })
278
- }
279
- return merged
280
- }
281
-
282
- /**
283
- * @param {IdSet} idset
284
- * @param {Array<AttributionItem<any>>} attrs
285
- */
286
- export const createIdMapFromIdSet = (idset, attrs) => {
287
- const idmap = createIdMap()
288
- // map attrs to idmap
289
- attrs = _ensureAttrs(idmap, attrs)
290
- // filter out duplicates
291
- /**
292
- * @type {Array<AttributionItem<any>>}
293
- */
294
- const checkedAttrs = []
295
- attrs.forEach(attr => {
296
- if (!idmapAttrsHas(checkedAttrs, attr)) {
297
- checkedAttrs.push(attr)
298
- }
299
- })
300
- idset.clients.forEach((ranges, client) => {
301
- const attrRanges = new AttrRanges(ranges.getIds().map(range => new AttrRange(range.clock, range.len, checkedAttrs)))
302
- attrRanges.sorted = true // is sorted because idset is sorted
303
- idmap.clients.set(client, attrRanges)
304
- })
305
- return idmap
306
- }
307
-
308
- /**
309
- * @template Attrs
310
- */
311
- export class IdMap {
312
- constructor () {
313
- /**
314
- * @type {Map<number,AttrRanges<Attrs>>}
315
- */
316
- this.clients = new Map()
317
- /**
318
- * @type {Map<string, AttributionItem<Attrs>>}
319
- */
320
- this.attrsH = new Map()
321
- /**
322
- * @type {Set<AttributionItem<Attrs>>}
323
- */
324
- this.attrs = new Set()
325
- }
326
-
327
- /**
328
- * @param {(attrRange:AttrRange<Attrs>, client:number) => void} f
329
- */
330
- forEach (f) {
331
- this.clients.forEach((ranges, client) => {
332
- ranges.getIds().forEach((range) => {
333
- f(range, client)
334
- })
335
- })
336
- }
337
-
338
- /**
339
- * @param {ID} id
340
- * @return {boolean}
341
- */
342
- hasId (id) {
343
- return this.has(id.client, id.clock)
344
- }
345
-
346
- /**
347
- * @param {number} client
348
- * @param {number} clock
349
- * @return {boolean}
350
- */
351
- has (client, clock) {
352
- const dr = this.clients.get(client)
353
- if (dr) {
354
- return findIndexInIdRanges(dr.getIds(), clock) !== null
355
- }
356
- return false
357
- }
358
-
359
- /**
360
- * Return attributions for a slice of ids.
361
- *
362
- * @param {ID} id
363
- * @param {number} len
364
- * @return {Array<MaybeAttrRange<Attrs>>}
365
- */
366
- sliceId (id, len) {
367
- return this.slice(id.client, id.clock, len)
368
- }
369
-
370
- /**
371
- * Return attributions for a slice of ids.
372
- *
373
- * @param {number} client
374
- * @param {number} clock
375
- * @param {number} len
376
- * @return {Array<MaybeAttrRange<Attrs>>}
377
- */
378
- slice (client, clock, len) {
379
- const dr = this.clients.get(client)
380
- /**
381
- * @type {Array<MaybeAttrRange<Attrs>>}
382
- */
383
- const res = []
384
- if (dr) {
385
- /**
386
- * @type {Array<AttrRange<Attrs>>}
387
- */
388
- const ranges = dr.getIds()
389
- let index = findRangeStartInIdRanges(ranges, clock)
390
- if (index !== null) {
391
- let prev = null
392
- while (index < ranges.length) {
393
- let r = ranges[index]
394
- if (r.clock < clock) {
395
- r = new AttrRange(clock, r.len - (clock - r.clock), r.attrs)
396
- }
397
- if (r.clock + r.len > clock + len) {
398
- r = new AttrRange(r.clock, clock + len - r.clock, r.attrs)
399
- }
400
- if (r.len <= 0) break
401
- const prevEnd = prev != null ? prev.clock + prev.len : clock
402
- if (prevEnd < r.clock) {
403
- res.push(createMaybeAttrRange(prevEnd, r.clock - prevEnd, null))
404
- }
405
- prev = r
406
- res.push(r)
407
- index++
408
- }
409
- }
410
- }
411
- if (res.length > 0) {
412
- const last = res[res.length - 1]
413
- const end = last.clock + last.len
414
- if (end < clock + len) {
415
- res.push(createMaybeAttrRange(end, clock + len - end, null))
416
- }
417
- } else {
418
- res.push(createMaybeAttrRange(clock, len, null))
419
- }
420
- return res
421
- }
422
-
423
- /**
424
- * @param {number} client
425
- * @param {number} clock
426
- * @param {number} len
427
- * @param {Array<AttributionItem<Attrs>>} attrs
428
- */
429
- add (client, clock, len, attrs) {
430
- if (len === 0) return
431
- attrs = _ensureAttrs(this, attrs)
432
- const ranges = this.clients.get(client)
433
- if (ranges == null) {
434
- this.clients.set(client, new AttrRanges([new AttrRange(clock, len, attrs)]))
435
- } else {
436
- ranges.add(clock, len, attrs)
437
- }
438
- }
439
-
440
- /**
441
- * @param {number} client
442
- * @param {number} clock
443
- * @param {number} len
444
- */
445
- delete (client, clock, len) {
446
- _deleteRangeFromIdSet(this, client, clock, len)
447
- }
448
- }
449
-
450
- /**
451
- * Efficiently encodes IdMap to a binary form. Ensures that information is de-duplicated when
452
- * written. Attribute.names are referenced by id. Attributes themselfs are also referenced by id.
453
- *
454
- * @template Attr
455
- * @param {IdSetEncoderV1 | IdSetEncoderV2} encoder
456
- * @param {IdMap<Attr>} idmap
457
- *
458
- * @private
459
- * @function
460
- */
461
- export const writeIdMap = (encoder, idmap) => {
462
- encoding.writeVarUint(encoder.restEncoder, idmap.clients.size)
463
- let lastWrittenClientId = 0
464
- /**
465
- * @type {Map<AttributionItem<Attr>, number>}
466
- */
467
- const visitedAttributions = map.create()
468
- /**
469
- * @type {Map<string, number>}
470
- */
471
- const visitedAttrNames = map.create()
472
- // Ensure that the ids are written in a deterministic order (smaller clientids first)
473
- array.from(idmap.clients.entries())
474
- .sort((a, b) => a[0] - b[0])
475
- .forEach(([client, _idRanges]) => {
476
- const attrRanges = _idRanges.getIds()
477
- encoder.resetIdSetCurVal()
478
- const diff = client - lastWrittenClientId
479
- encoding.writeVarUint(encoder.restEncoder, diff)
480
- lastWrittenClientId = client
481
- const len = attrRanges.length
482
- encoding.writeVarUint(encoder.restEncoder, len)
483
- for (let i = 0; i < len; i++) {
484
- const item = attrRanges[i]
485
- const attrs = item.attrs
486
- const attrLen = attrs.length
487
- encoder.writeIdSetClock(item.clock)
488
- encoder.writeIdSetLen(item.len)
489
- encoding.writeVarUint(encoder.restEncoder, attrLen)
490
- for (let j = 0; j < attrLen; j++) {
491
- const attr = attrs[j]
492
- const attrId = visitedAttributions.get(attr)
493
- if (attrId != null) {
494
- encoding.writeVarUint(encoder.restEncoder, attrId)
495
- } else {
496
- const newAttrId = visitedAttributions.size
497
- visitedAttributions.set(attr, newAttrId)
498
- encoding.writeVarUint(encoder.restEncoder, newAttrId)
499
- const attrNameId = visitedAttrNames.get(attr.name)
500
- // write attr.name
501
- if (attrNameId != null) {
502
- encoding.writeVarUint(encoder.restEncoder, attrNameId)
503
- } else {
504
- const newAttrNameId = visitedAttrNames.size
505
- encoding.writeVarUint(encoder.restEncoder, newAttrNameId)
506
- encoding.writeVarString(encoder.restEncoder, attr.name)
507
- visitedAttrNames.set(attr.name, newAttrNameId)
508
- }
509
- encoding.writeAny(encoder.restEncoder, /** @type {any} */ (attr.val))
510
- }
511
- }
512
- }
513
- })
514
- }
515
-
516
- /**
517
- * @param {IdMap<any>} idmap
518
- */
519
- export const encodeIdMap = idmap => {
520
- const encoder = new IdSetEncoderV2()
521
- writeIdMap(encoder, idmap)
522
- return encoder.toUint8Array()
523
- }
524
-
525
- /**
526
- * @param {DSDecoderV1 | DSDecoderV2} decoder
527
- * @return {IdMap<any>}
528
- *
529
- * @private
530
- * @function
531
- */
532
- export const readIdMap = decoder => {
533
- const idmap = new IdMap()
534
- const numClients = decoding.readVarUint(decoder.restDecoder)
535
- /**
536
- * @type {Array<AttributionItem<any>>}
537
- */
538
- const visitedAttributions = []
539
- /**
540
- * @type {Array<string>}
541
- */
542
- const visitedAttrNames = []
543
- let lastClientId = 0
544
- for (let i = 0; i < numClients; i++) {
545
- decoder.resetDsCurVal()
546
- const client = lastClientId + decoding.readVarUint(decoder.restDecoder)
547
- lastClientId = client
548
- const numberOfDeletes = decoding.readVarUint(decoder.restDecoder)
549
- /**
550
- * @type {Array<AttrRange<any>>}
551
- */
552
- const attrRanges = []
553
- for (let i = 0; i < numberOfDeletes; i++) {
554
- const rangeClock = decoder.readDsClock()
555
- const rangeLen = decoder.readDsLen()
556
- /**
557
- * @type {Array<AttributionItem<any>>}
558
- */
559
- const attrs = []
560
- const attrsLen = decoding.readVarUint(decoder.restDecoder)
561
- for (let j = 0; j < attrsLen; j++) {
562
- const attrId = decoding.readVarUint(decoder.restDecoder)
563
- if (attrId >= visitedAttributions.length) {
564
- // attrId not known yet
565
- const attrNameId = decoding.readVarUint(decoder.restDecoder)
566
- if (attrNameId >= visitedAttrNames.length) {
567
- visitedAttrNames.push(decoding.readVarString(decoder.restDecoder))
568
- }
569
- visitedAttributions.push(new AttributionItem(visitedAttrNames[attrNameId], decoding.readAny(decoder.restDecoder)))
570
- }
571
- attrs.push(visitedAttributions[attrId])
572
- }
573
- attrRanges.push(new AttrRange(rangeClock, rangeLen, attrs))
574
- }
575
- idmap.clients.set(client, new AttrRanges(attrRanges))
576
- }
577
- visitedAttributions.forEach(attr => {
578
- idmap.attrs.add(attr)
579
- idmap.attrsH.set(attr.hash(), attr)
580
- })
581
- return idmap
582
- }
583
-
584
- /**
585
- * @param {Uint8Array} data
586
- * @return {IdMap<any>}
587
- */
588
- export const decodeIdMap = data => readIdMap(new DSDecoderV2(decoding.createDecoder(data)))
589
-
590
- /**
591
- * @template Attrs
592
- * @param {IdMap<Attrs>} idmap
593
- * @param {Array<AttributionItem<Attrs>>} attrs
594
- * @return {Array<AttributionItem<Attrs>>}
595
- */
596
- const _ensureAttrs = (idmap, attrs) => attrs.map(attr =>
597
- idmap.attrs.has(attr)
598
- ? attr
599
- : map.setIfUndefined(idmap.attrsH, _hashAttribution(attr), () => {
600
- idmap.attrs.add(attr)
601
- return attr
602
- }))
603
-
604
- export const createIdMap = () => new IdMap()
605
-
606
- /**
607
- * @template T
608
- * @param {IdMap<T>} dest
609
- * @param {IdMap<T>} src
610
- */
611
- export const insertIntoIdMap = _insertIntoIdSet
612
-
613
- /**
614
- * Remove all ranges from `exclude` from `ds`. The result is a fresh IdMap containing all ranges from `idSet` that are not
615
- * in `exclude`.
616
- *
617
- * @template {IdMap<any>} ISet
618
- * @param {ISet} set
619
- * @param {IdSet | IdMap<any>} exclude
620
- * @return {ISet}
621
- */
622
- export const diffIdMap = (set, exclude) => {
623
- const diffed = _diffSet(set, exclude)
624
- diffed.attrs = set.attrs
625
- diffed.attrsH = set.attrsH
626
- return diffed
627
- }
628
-
629
- export const intersectMaps = _intersectSets