@cloudbitmaps/roaring 0.24.0 → 0.26.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/dist/index.js CHANGED
@@ -119,14 +119,99 @@ function refuseReservedNamespace(namespace) {
119
119
  }
120
120
  }
121
121
 
122
- // src/roaring-codec.ts
123
- import { ValidationError as ValidationError3, decodeSerialized } from "@cloudbitmaps/core";
124
-
125
122
  // src/ts-roaring/bitmap.ts
126
- import { IntegrityError as IntegrityError3, ValidationError as ValidationError2 } from "@cloudbitmaps/core";
123
+ import { IntegrityError as IntegrityError3, ValidationError as ValidationError2, refusalOfId } from "@cloudbitmaps/core";
127
124
 
128
125
  // src/portable/layout.ts
129
126
  import { IntegrityError } from "@cloudbitmaps/core";
127
+
128
+ // src/portable/popcount.ts
129
+ var BITSET_WORDS = 2048;
130
+ function popcount32(word) {
131
+ let w = word - (word >>> 1 & 1431655765);
132
+ w = (w & 858993459) + (w >>> 2 & 858993459);
133
+ return Math.imul(w + (w >>> 4) & 252645135, 16843009) >>> 24;
134
+ }
135
+ function popcountWords(d) {
136
+ let total = 0;
137
+ let ones = 0;
138
+ let twos = 0;
139
+ let fours = 0;
140
+ let eights = 0;
141
+ for (let i = 0; i < BITSET_WORDS; i += 16) {
142
+ let u;
143
+ let twosA;
144
+ let twosB;
145
+ let foursA;
146
+ let foursB;
147
+ let x = d[i];
148
+ let y = d[i + 1];
149
+ u = ones ^ x;
150
+ twosA = ones & x | u & y;
151
+ ones = u ^ y;
152
+ x = d[i + 2];
153
+ y = d[i + 3];
154
+ u = ones ^ x;
155
+ twosB = ones & x | u & y;
156
+ ones = u ^ y;
157
+ u = twos ^ twosA;
158
+ foursA = twos & twosA | u & twosB;
159
+ twos = u ^ twosB;
160
+ x = d[i + 4];
161
+ y = d[i + 5];
162
+ u = ones ^ x;
163
+ twosA = ones & x | u & y;
164
+ ones = u ^ y;
165
+ x = d[i + 6];
166
+ y = d[i + 7];
167
+ u = ones ^ x;
168
+ twosB = ones & x | u & y;
169
+ ones = u ^ y;
170
+ u = twos ^ twosA;
171
+ foursB = twos & twosA | u & twosB;
172
+ twos = u ^ twosB;
173
+ u = fours ^ foursA;
174
+ const eightsA = fours & foursA | u & foursB;
175
+ fours = u ^ foursB;
176
+ x = d[i + 8];
177
+ y = d[i + 9];
178
+ u = ones ^ x;
179
+ twosA = ones & x | u & y;
180
+ ones = u ^ y;
181
+ x = d[i + 10];
182
+ y = d[i + 11];
183
+ u = ones ^ x;
184
+ twosB = ones & x | u & y;
185
+ ones = u ^ y;
186
+ u = twos ^ twosA;
187
+ foursA = twos & twosA | u & twosB;
188
+ twos = u ^ twosB;
189
+ x = d[i + 12];
190
+ y = d[i + 13];
191
+ u = ones ^ x;
192
+ twosA = ones & x | u & y;
193
+ ones = u ^ y;
194
+ x = d[i + 14];
195
+ y = d[i + 15];
196
+ u = ones ^ x;
197
+ twosB = ones & x | u & y;
198
+ ones = u ^ y;
199
+ u = twos ^ twosA;
200
+ foursB = twos & twosA | u & twosB;
201
+ twos = u ^ twosB;
202
+ u = fours ^ foursA;
203
+ const eightsB = fours & foursA | u & foursB;
204
+ fours = u ^ foursB;
205
+ u = eights ^ eightsA;
206
+ const sixteens = eights & eightsA | u & eightsB;
207
+ eights = u ^ eightsB;
208
+ total += popcount32(sixteens);
209
+ }
210
+ return 16 * total + 8 * popcount32(eights) + 4 * popcount32(fours) + 2 * popcount32(twos) + popcount32(ones);
211
+ }
212
+
213
+ // src/portable/layout.ts
214
+ var LITTLE_ENDIAN = new Uint8Array(Uint16Array.of(1).buffer)[0] === 1;
130
215
  var SERIAL_COOKIE_NO_RUNCONTAINER = 12346;
131
216
  var SERIAL_COOKIE = 12347;
132
217
  var NO_OFFSET_THRESHOLD = 4;
@@ -191,7 +276,7 @@ function walk(bytes, out) {
191
276
  const key = view.getUint16(descriptiveAt + i * 4, true);
192
277
  if (key <= previousKey) {
193
278
  throw new IntegrityError(
194
- `portable roaring: container keys are not strictly ascending (${previousKey} then ${key} at index ${i})`
279
+ `portable roaring: container keys are not strictly ascending at index ${i}`
195
280
  );
196
281
  }
197
282
  previousKey = key;
@@ -224,7 +309,7 @@ function checkContainer(bytes, view, pos, kind, cardinality, i) {
224
309
  if (pos + BITMAP_CONTAINER_BYTES > length) {
225
310
  throw overrun(bytes, pos, BITMAP_CONTAINER_BYTES, `container ${i} (bitmap)`);
226
311
  }
227
- const bits = popcount(view, pos);
312
+ const bits = bitsetBits(bytes, pos);
228
313
  if (bits !== cardinality) {
229
314
  throw new IntegrityError(
230
315
  `portable roaring: container ${i} (bitmap) holds ${bits} values, but its header says ${cardinality}`
@@ -284,25 +369,22 @@ function checkRuns(view, at, runs, index) {
284
369
  }
285
370
  return covered;
286
371
  }
287
- function popcount(view, at) {
288
- let bits = 0;
289
- for (let p = at, end = at + BITMAP_CONTAINER_BYTES; p < end; p += 4) {
290
- let w = view.getUint32(p, true);
291
- w -= w >>> 1 & 1431655765;
292
- w = (w & 858993459) + (w >>> 2 & 858993459);
293
- bits += Math.imul(w + (w >>> 4) & 252645135, 16843009) >>> 24;
294
- }
295
- return bits;
372
+ function bitsetBits(bytes, at) {
373
+ const offset = bytes.byteOffset + at;
374
+ if ((offset & 3) === 0) return popcountWords(new Uint32Array(bytes.buffer, offset, BITSET_WORDS));
375
+ scratchBytes.set(bytes.subarray(at, at + BITMAP_CONTAINER_BYTES));
376
+ return popcountWords(scratchWords);
296
377
  }
378
+ var scratchWords = new Uint32Array(BITSET_WORDS);
379
+ var scratchBytes = new Uint8Array(scratchWords.buffer);
297
380
 
298
381
  // src/ts-roaring/containers.ts
299
382
  var ARRAY2 = 0;
300
383
  var BITSET = 1;
301
384
  var RUN2 = 2;
302
- var WORDS = 2048;
385
+ var WORDS = BITSET_WORDS;
303
386
  var BITSET_BYTES = 8192;
304
387
  var GALLOP_SKEW = 16;
305
- var LITTLE_ENDIAN = new Uint8Array(Uint16Array.of(1).buffer)[0] === 1;
306
388
  var Container = class {
307
389
  constructor(kind, data, off, len, card, shared) {
308
390
  this.kind = kind;
@@ -352,12 +434,7 @@ function pairs16(n) {
352
434
  function arrayOfScratch(scratch, n) {
353
435
  return n === 0 ? null : arrayContainer(scratch.slice(0, n), n);
354
436
  }
355
- function popcount32(word) {
356
- let w = word - (word >>> 1 & 1431655765);
357
- w = (w & 858993459) + (w >>> 2 & 858993459);
358
- return Math.imul(w + (w >>> 4) & 252645135, 16843009) >>> 24;
359
- }
360
- function popcountWords(d) {
437
+ function popcountAnd(d, e) {
361
438
  let total = 0;
362
439
  let ones = 0;
363
440
  let twos = 0;
@@ -369,26 +446,26 @@ function popcountWords(d) {
369
446
  let twosB;
370
447
  let foursA;
371
448
  let foursB;
372
- let x = d[i];
373
- let y = d[i + 1];
449
+ let x = d[i] & e[i];
450
+ let y = d[i + 1] & e[i + 1];
374
451
  u = ones ^ x;
375
452
  twosA = ones & x | u & y;
376
453
  ones = u ^ y;
377
- x = d[i + 2];
378
- y = d[i + 3];
454
+ x = d[i + 2] & e[i + 2];
455
+ y = d[i + 3] & e[i + 3];
379
456
  u = ones ^ x;
380
457
  twosB = ones & x | u & y;
381
458
  ones = u ^ y;
382
459
  u = twos ^ twosA;
383
460
  foursA = twos & twosA | u & twosB;
384
461
  twos = u ^ twosB;
385
- x = d[i + 4];
386
- y = d[i + 5];
462
+ x = d[i + 4] & e[i + 4];
463
+ y = d[i + 5] & e[i + 5];
387
464
  u = ones ^ x;
388
465
  twosA = ones & x | u & y;
389
466
  ones = u ^ y;
390
- x = d[i + 6];
391
- y = d[i + 7];
467
+ x = d[i + 6] & e[i + 6];
468
+ y = d[i + 7] & e[i + 7];
392
469
  u = ones ^ x;
393
470
  twosB = ones & x | u & y;
394
471
  ones = u ^ y;
@@ -398,26 +475,26 @@ function popcountWords(d) {
398
475
  u = fours ^ foursA;
399
476
  const eightsA = fours & foursA | u & foursB;
400
477
  fours = u ^ foursB;
401
- x = d[i + 8];
402
- y = d[i + 9];
478
+ x = d[i + 8] & e[i + 8];
479
+ y = d[i + 9] & e[i + 9];
403
480
  u = ones ^ x;
404
481
  twosA = ones & x | u & y;
405
482
  ones = u ^ y;
406
- x = d[i + 10];
407
- y = d[i + 11];
483
+ x = d[i + 10] & e[i + 10];
484
+ y = d[i + 11] & e[i + 11];
408
485
  u = ones ^ x;
409
486
  twosB = ones & x | u & y;
410
487
  ones = u ^ y;
411
488
  u = twos ^ twosA;
412
489
  foursA = twos & twosA | u & twosB;
413
490
  twos = u ^ twosB;
414
- x = d[i + 12];
415
- y = d[i + 13];
491
+ x = d[i + 12] & e[i + 12];
492
+ y = d[i + 13] & e[i + 13];
416
493
  u = ones ^ x;
417
494
  twosA = ones & x | u & y;
418
495
  ones = u ^ y;
419
- x = d[i + 14];
420
- y = d[i + 15];
496
+ x = d[i + 14] & e[i + 14];
497
+ y = d[i + 15] & e[i + 15];
421
498
  u = ones ^ x;
422
499
  twosB = ones & x | u & y;
423
500
  ones = u ^ y;
@@ -460,6 +537,19 @@ function clearRange(words, start, end) {
460
537
  for (let i = first + 1; i < last; i++) words[i] = 0;
461
538
  words[last] = words[last] & ~tail;
462
539
  }
540
+ function flipRange(words, start, end) {
541
+ const first = start >>> 5;
542
+ const last = end >>> 5;
543
+ const head = 4294967295 << (start & 31) >>> 0;
544
+ const tail = 4294967295 >>> 31 - (end & 31);
545
+ if (first === last) {
546
+ words[first] = words[first] ^ head & tail;
547
+ return;
548
+ }
549
+ words[first] = words[first] ^ head;
550
+ for (let i = first + 1; i < last; i++) words[i] = ~words[i];
551
+ words[last] = words[last] ^ tail;
552
+ }
463
553
  function fromSortedIds(ids, from, to) {
464
554
  const n = to - from;
465
555
  if (n <= ARRAY_MAX_CARDINALITY) {
@@ -515,11 +605,12 @@ function writeLows(c, out) {
515
605
  }
516
606
  }
517
607
  }
608
+ var SMALL_IDS = 32;
518
609
  function appendIds(c, out, at, base) {
519
610
  if (c.kind === ARRAY2) {
520
611
  const u162 = lows16(c);
521
612
  const end = c.off + c.len;
522
- if (base === 0) {
613
+ if (base === 0 && c.len >= SMALL_IDS) {
523
614
  out.set(u162.subarray(c.off, end), at);
524
615
  return at + c.len;
525
616
  }
@@ -542,14 +633,15 @@ function appendIds(c, out, at, base) {
542
633
  const u16 = lows16(c);
543
634
  for (let r = 0; r < c.len; r++) {
544
635
  const start = u16[c.off + 2 * r];
545
- const last = start + u16[c.off + 2 * r + 1];
546
- if (last - start < LONG_RUN) {
547
- for (let v = base + start; v <= base + last; v++) out[at++] = v;
636
+ const length = u16[c.off + 2 * r + 1];
637
+ if (length < LONG_RUN) {
638
+ const last = base + start + length;
639
+ for (let v = base + start; v <= last; v++) out[at++] = v;
548
640
  continue;
549
641
  }
550
642
  const from = at;
551
- out.set(iota().subarray(start, last + 1), at);
552
- at += last - start + 1;
643
+ out.set(iota().subarray(start, start + length + 1), at);
644
+ at += length + 1;
553
645
  if (base !== 0) for (let i = from; i < at; i++) out[i] = out[i] + base;
554
646
  }
555
647
  return at;
@@ -635,31 +727,130 @@ function containerHas(c, low) {
635
727
  const r = c.off + 2 * (after - 1);
636
728
  return low <= u16[r] + u16[r + 1];
637
729
  }
730
+ function runsAfter(data, off, from, len, value) {
731
+ let step = 1;
732
+ let lo = from;
733
+ let hi = from;
734
+ while (hi < len && data[off + 2 * hi] <= value) {
735
+ lo = hi + 1;
736
+ hi += step;
737
+ step *= 2;
738
+ }
739
+ if (hi > len) hi = len;
740
+ while (lo < hi) {
741
+ const mid = lo + hi >>> 1;
742
+ if (data[off + 2 * mid] <= value) lo = mid + 1;
743
+ else hi = mid;
744
+ }
745
+ return lo;
746
+ }
747
+ function runsOrPlain(pairs, runs, card, copy) {
748
+ const plain = card <= ARRAY_MAX_CARDINALITY ? 2 * card : BITSET_BYTES;
749
+ if (2 + 4 * runs < plain) {
750
+ return runContainer(copy ? pairs.slice(0, 2 * runs) : pairs, runs, card);
751
+ }
752
+ return fromRunPairs(pairs, runs, card);
753
+ }
754
+ function addToRuns(c, low) {
755
+ const u16 = lows16(c);
756
+ const next = runsAfter(u16, c.off, 0, c.len, low);
757
+ const prev = next - 1;
758
+ const joinPrev = prev >= 0 && u16[c.off + 2 * prev] + u16[c.off + 2 * prev + 1] + 1 === low;
759
+ const joinNext = next < c.len && u16[c.off + 2 * next] === low + 1;
760
+ const runs = c.len + 1 - (joinPrev ? 1 : 0) - (joinNext ? 1 : 0);
761
+ const out = new Uint16Array(2 * runs);
762
+ const head = joinPrev ? prev : next;
763
+ out.set(u16.subarray(c.off, c.off + 2 * head));
764
+ let at = 2 * head;
765
+ if (joinPrev && joinNext) {
766
+ out[at++] = u16[c.off + 2 * prev];
767
+ out[at++] = u16[c.off + 2 * next] + u16[c.off + 2 * next + 1] - u16[c.off + 2 * prev];
768
+ } else if (joinPrev) {
769
+ out[at++] = u16[c.off + 2 * prev];
770
+ out[at++] = u16[c.off + 2 * prev + 1] + 1;
771
+ } else if (joinNext) {
772
+ out[at++] = low;
773
+ out[at++] = u16[c.off + 2 * next + 1] + 1;
774
+ } else {
775
+ out[at++] = low;
776
+ out[at++] = 0;
777
+ }
778
+ const rest = joinNext ? next + 1 : next;
779
+ out.set(u16.subarray(c.off + 2 * rest, c.off + 2 * c.len), at);
780
+ return runsOrPlain(out, runs, c.card + 1, false);
781
+ }
638
782
  function containerAdd(c, low) {
639
783
  if (containerHas(c, low)) return c;
640
- const plain = demote(c);
641
- if (plain.kind === BITSET) {
642
- const words = writableWords(plain);
784
+ if (c.kind === RUN2) return addToRuns(c, low);
785
+ if (c.kind === BITSET) {
786
+ const words = writableWords(c);
643
787
  words[low >>> 5] = words[low >>> 5] | 1 << (low & 31);
644
- return bitsetContainer(words, plain.card + 1);
788
+ return bitsetContainer(words, c.card + 1);
645
789
  }
646
- if (plain.card === ARRAY_MAX_CARDINALITY) {
647
- const words = toWords(plain);
790
+ if (c.card === ARRAY_MAX_CARDINALITY) {
791
+ const words = toWords(c);
648
792
  words[low >>> 5] = words[low >>> 5] | 1 << (low & 31);
649
- return bitsetContainer(words, plain.card + 1);
793
+ return bitsetContainer(words, c.card + 1);
650
794
  }
651
- const old = lows16(plain);
652
- const at = lowerBound(old, plain.off, plain.len, low, 1);
795
+ const old = lows16(c);
796
+ const at = lowerBound(old, c.off, c.len, low, 1);
653
797
  let u16 = old;
654
- if (!plain.shared && plain.off === 0 && old.length > plain.len) {
655
- u16.copyWithin(at + 1, at, plain.len);
798
+ if (!c.shared && c.off === 0 && old.length > c.len) {
799
+ u16.copyWithin(at + 1, at, c.len);
656
800
  } else {
657
- u16 = new Uint16Array(Math.min(ARRAY_MAX_CARDINALITY, Math.max(8, plain.len * 2)));
658
- u16.set(old.subarray(plain.off, plain.off + at));
659
- u16.set(old.subarray(plain.off + at, plain.off + plain.len), at + 1);
801
+ u16 = new Uint16Array(Math.min(ARRAY_MAX_CARDINALITY, Math.max(8, c.len * 2)));
802
+ u16.set(old.subarray(c.off, c.off + at));
803
+ u16.set(old.subarray(c.off + at, c.off + c.len), at + 1);
660
804
  }
661
805
  u16[at] = low;
662
- return arrayContainer(u16, plain.card + 1);
806
+ return arrayContainer(u16, c.card + 1);
807
+ }
808
+ function addFewToRuns(c, ids, from, to) {
809
+ const x = lows16(c);
810
+ let data = x;
811
+ let base = c.off;
812
+ let out = null;
813
+ let n = c.len;
814
+ let added = 0;
815
+ for (let k = from; k < to; k++) {
816
+ const low = ids[k] & 65535;
817
+ const next = runsAfter(data, base, 0, n, low);
818
+ const prev = next - 1;
819
+ const prevEnd = prev >= 0 ? data[base + 2 * prev] + data[base + 2 * prev + 1] : -2;
820
+ if (prevEnd >= low) continue;
821
+ if (out === null) {
822
+ out = new Uint16Array(2 * (c.len + to - from));
823
+ out.set(x.subarray(c.off, c.off + 2 * c.len));
824
+ data = out;
825
+ base = 0;
826
+ }
827
+ const joinPrev = prevEnd + 1 === low;
828
+ const joinNext = next < n && out[2 * next] === low + 1;
829
+ if (joinPrev && joinNext) {
830
+ out[2 * prev + 1] = out[2 * next] + out[2 * next + 1] - out[2 * prev];
831
+ out.copyWithin(2 * next, 2 * next + 2, 2 * n);
832
+ n--;
833
+ } else if (joinPrev) {
834
+ out[2 * prev + 1] = out[2 * prev + 1] + 1;
835
+ } else if (joinNext) {
836
+ out[2 * next] = low;
837
+ out[2 * next + 1] = out[2 * next + 1] + 1;
838
+ } else {
839
+ out.copyWithin(2 * next + 2, 2 * next, 2 * n);
840
+ out[2 * next] = low;
841
+ out[2 * next + 1] = 0;
842
+ n++;
843
+ }
844
+ added++;
845
+ }
846
+ if (out === null) return c;
847
+ return runsOrPlain(out, n, c.card + added, true);
848
+ }
849
+ function containerAddSorted(c, ids, from, to) {
850
+ if (c.kind === RUN2) return addFewToRuns(c, ids, from, to);
851
+ let cur = c;
852
+ for (let k = from; k < to; k++) cur = containerAdd(cur, ids[k] & 65535);
853
+ return cur;
663
854
  }
664
855
  function containerRemove(c, low) {
665
856
  if (!containerHas(c, low)) return c;
@@ -681,6 +872,15 @@ function containerRemove(c, low) {
681
872
  u16.set(old.subarray(plain.off + at + 1, plain.off + plain.len), at);
682
873
  return arrayContainer(u16, plain.card - 1);
683
874
  }
875
+ function containerMin(c) {
876
+ if (c.kind === ARRAY2 || c.kind === RUN2) return c.data[c.off];
877
+ const words = words32(c);
878
+ for (let i = 0; i < WORDS; i++) {
879
+ const w = words[i];
880
+ if (w !== 0) return i * 32 + 31 - Math.clz32(w & -w);
881
+ }
882
+ throw new RangeError("a bitset container holds no bits");
883
+ }
684
884
  function containerMax(c) {
685
885
  if (c.kind === ARRAY2) return c.data[c.off + c.len - 1];
686
886
  if (c.kind === RUN2) {
@@ -775,6 +975,7 @@ function skewed(shorter, longer) {
775
975
  return longer >= GALLOP_SKEW * shorter;
776
976
  }
777
977
  var PROBE_MIN = 32;
978
+ var MERGE_FIRST = 64;
778
979
  var probeWords = new Uint32Array(WORDS);
779
980
  function andArrays(a, b) {
780
981
  const small = a.len <= b.len ? a : b;
@@ -949,6 +1150,70 @@ function orArrays(a, b) {
949
1150
  while (j < je) out[n++] = y[j++];
950
1151
  return arrayOfScratch(out, n);
951
1152
  }
1153
+ function andWords(out, x, y) {
1154
+ for (let i = 0; i < WORDS; i += 4) {
1155
+ const X0 = x[i];
1156
+ const Y0 = y[i];
1157
+ const X1 = x[i + 1];
1158
+ const Y1 = y[i + 1];
1159
+ const X2 = x[i + 2];
1160
+ const Y2 = y[i + 2];
1161
+ const X3 = x[i + 3];
1162
+ const Y3 = y[i + 3];
1163
+ out[i] = X0 & Y0;
1164
+ out[i + 1] = X1 & Y1;
1165
+ out[i + 2] = X2 & Y2;
1166
+ out[i + 3] = X3 & Y3;
1167
+ }
1168
+ }
1169
+ function orWords(out, x, y) {
1170
+ for (let i = 0; i < WORDS; i += 4) {
1171
+ const X0 = x[i];
1172
+ const Y0 = y[i];
1173
+ const X1 = x[i + 1];
1174
+ const Y1 = y[i + 1];
1175
+ const X2 = x[i + 2];
1176
+ const Y2 = y[i + 2];
1177
+ const X3 = x[i + 3];
1178
+ const Y3 = y[i + 3];
1179
+ out[i] = X0 | Y0;
1180
+ out[i + 1] = X1 | Y1;
1181
+ out[i + 2] = X2 | Y2;
1182
+ out[i + 3] = X3 | Y3;
1183
+ }
1184
+ }
1185
+ function xorWords(out, x, y) {
1186
+ for (let i = 0; i < WORDS; i += 4) {
1187
+ const X0 = x[i];
1188
+ const Y0 = y[i];
1189
+ const X1 = x[i + 1];
1190
+ const Y1 = y[i + 1];
1191
+ const X2 = x[i + 2];
1192
+ const Y2 = y[i + 2];
1193
+ const X3 = x[i + 3];
1194
+ const Y3 = y[i + 3];
1195
+ out[i] = X0 ^ Y0;
1196
+ out[i + 1] = X1 ^ Y1;
1197
+ out[i + 2] = X2 ^ Y2;
1198
+ out[i + 3] = X3 ^ Y3;
1199
+ }
1200
+ }
1201
+ function andNotWords(out, x, y) {
1202
+ for (let i = 0; i < WORDS; i += 4) {
1203
+ const X0 = x[i];
1204
+ const Y0 = y[i];
1205
+ const X1 = x[i + 1];
1206
+ const Y1 = y[i + 1];
1207
+ const X2 = x[i + 2];
1208
+ const Y2 = y[i + 2];
1209
+ const X3 = x[i + 3];
1210
+ const Y3 = y[i + 3];
1211
+ out[i] = X0 & ~Y0;
1212
+ out[i + 1] = X1 & ~Y1;
1213
+ out[i + 2] = X2 & ~Y2;
1214
+ out[i + 3] = X3 & ~Y3;
1215
+ }
1216
+ }
952
1217
  function orIntoBitset(dest, other, inPlace) {
953
1218
  const words = inPlace ? words32(dest) : words32(dest).slice();
954
1219
  if (other.kind === ARRAY2) {
@@ -966,8 +1231,7 @@ function orIntoBitset(dest, other, inPlace) {
966
1231
  return bitsetContainer(words, card);
967
1232
  }
968
1233
  if (other.kind === BITSET) {
969
- const o = words32(other);
970
- for (let i = 0; i < WORDS; i++) words[i] = words[i] | o[i];
1234
+ orWords(words, words, words32(other));
971
1235
  } else {
972
1236
  const pairs = lows16(other);
973
1237
  for (let r = 0; r < other.len; r++) {
@@ -977,6 +1241,81 @@ function orIntoBitset(dest, other, inPlace) {
977
1241
  }
978
1242
  return bitsetContainer(words, popcountWords(words));
979
1243
  }
1244
+ function orBitsetWords(list) {
1245
+ const bits = [];
1246
+ for (const c of list) if (c.kind === BITSET) bits.push(words32(c));
1247
+ const n = bits.length;
1248
+ if (n === 0) return new Uint32Array(WORDS);
1249
+ let k;
1250
+ let words;
1251
+ if (n >= 4) {
1252
+ const a = bits[0];
1253
+ const b = bits[1];
1254
+ const c = bits[2];
1255
+ const d = bits[3];
1256
+ words = new Uint32Array(WORDS);
1257
+ for (let i = 0; i < WORDS; i++)
1258
+ words[i] = a[i] | b[i] | c[i] | d[i];
1259
+ k = 4;
1260
+ } else {
1261
+ words = bits[0].slice();
1262
+ k = 1;
1263
+ }
1264
+ for (; k + 4 <= n; k += 4) {
1265
+ const a = bits[k];
1266
+ const b = bits[k + 1];
1267
+ const c = bits[k + 2];
1268
+ const d = bits[k + 3];
1269
+ for (let i = 0; i < WORDS; i++) {
1270
+ words[i] = words[i] | a[i] | b[i] | c[i] | d[i];
1271
+ }
1272
+ }
1273
+ for (; k < n; k++) {
1274
+ const o = bits[k];
1275
+ for (let i = 0; i < WORDS; i++) words[i] = words[i] | o[i];
1276
+ }
1277
+ return words;
1278
+ }
1279
+ function orManyContainers(list) {
1280
+ let total = 0;
1281
+ let allArrays = true;
1282
+ for (const c of list) {
1283
+ total += c.card;
1284
+ if (c.kind !== ARRAY2) allArrays = false;
1285
+ }
1286
+ if (allArrays && total <= ARRAY_MAX_CARDINALITY) {
1287
+ const out = values16(total);
1288
+ let n = 0;
1289
+ for (const c of list) {
1290
+ out.set(lows16(c).subarray(c.off, c.off + c.len), n);
1291
+ n += c.len;
1292
+ }
1293
+ const sorted = out.subarray(0, n).sort();
1294
+ let distinct = 0;
1295
+ for (let i = 0; i < n; i++) {
1296
+ const v = sorted[i];
1297
+ if (i === 0 || v !== sorted[distinct - 1]) sorted[distinct++] = v;
1298
+ }
1299
+ return arrayContainer(sorted.slice(0, distinct), distinct);
1300
+ }
1301
+ const words = orBitsetWords(list);
1302
+ for (const c of list) {
1303
+ if (c.kind === ARRAY2) {
1304
+ const u16 = lows16(c);
1305
+ for (let i = c.off; i < c.off + c.len; i++) {
1306
+ const v = u16[i];
1307
+ words[v >>> 5] = words[v >>> 5] | 1 << (v & 31);
1308
+ }
1309
+ } else if (c.kind === RUN2) {
1310
+ const pairs = lows16(c);
1311
+ for (let r = 0; r < c.len; r++) {
1312
+ const start = pairs[c.off + 2 * r];
1313
+ setRange(words, start, start + pairs[c.off + 2 * r + 1]);
1314
+ }
1315
+ }
1316
+ }
1317
+ return fromWordsCard(words, popcountWords(words));
1318
+ }
980
1319
  function fromRunPairs(pairs, runs, card) {
981
1320
  if (card === 0) return null;
982
1321
  if (card <= ARRAY_MAX_CARDINALITY) {
@@ -1020,7 +1359,7 @@ function andRuns(a, b) {
1020
1359
  if (ae < be) i++;
1021
1360
  else j++;
1022
1361
  }
1023
- return fromRunPairs(out, runs, card);
1362
+ return card === 0 ? null : runsOrPlain(out, runs, card, true);
1024
1363
  }
1025
1364
  function orRuns(a, b) {
1026
1365
  const x = lows16(a);
@@ -1060,7 +1399,7 @@ function orRuns(a, b) {
1060
1399
  }
1061
1400
  }
1062
1401
  flush();
1063
- return fromRunPairs(out, runs, card);
1402
+ return runsOrPlain(out, runs, card, true);
1064
1403
  }
1065
1404
  function andNotRuns(a, b) {
1066
1405
  const x = lows16(a);
@@ -1094,7 +1433,7 @@ function andNotRuns(a, b) {
1094
1433
  k++;
1095
1434
  }
1096
1435
  }
1097
- return fromRunPairs(out, runs, card);
1436
+ return card === 0 ? null : runsOrPlain(out, runs, card, true);
1098
1437
  }
1099
1438
  function bitsetInRuns(a, b) {
1100
1439
  const words = words32(a);
@@ -1146,7 +1485,7 @@ function containerAnd(a, b, inPlace = false) {
1146
1485
  const x = words32(a);
1147
1486
  const y = words32(b);
1148
1487
  const out = inPlace ? x : new Uint32Array(WORDS);
1149
- for (let i = 0; i < WORDS; i++) out[i] = x[i] & y[i];
1488
+ andWords(out, x, y);
1150
1489
  return fromWordsCard(out, popcountWords(out));
1151
1490
  }
1152
1491
  if (a.kind > b.kind) return containerAnd(b, a);
@@ -1161,16 +1500,162 @@ function containerOr(a, b, inPlace = false) {
1161
1500
  if (b.kind === BITSET) return orIntoBitset(b, a, false);
1162
1501
  if (a.kind === ARRAY2 && b.kind === ARRAY2) return orArrays(a, b);
1163
1502
  if (a.kind === RUN2 && b.kind === RUN2) return orRuns(a, b);
1164
- const words = toWords(a.kind === RUN2 ? a : b);
1165
- return orIntoBitsetWords(words, a.kind === RUN2 ? b : a);
1503
+ return a.kind === RUN2 ? orRunArray(a, b, inPlace) : orRunArray(b, a, false);
1166
1504
  }
1167
- function orIntoBitsetWords(words, array) {
1168
- const u16 = lows16(array);
1505
+ var EXPAND_MIN_STEPS = 1024;
1506
+ function expandsRunArray(runs, array) {
1507
+ return expandsRunSteps(runs, array.len);
1508
+ }
1509
+ function expandsRunSteps(runs, values) {
1510
+ const steps = runs.len + values;
1511
+ if (steps < EXPAND_MIN_STEPS) return false;
1512
+ const cardMax = runs.card + values;
1513
+ const plainMax = cardMax <= ARRAY_MAX_CARDINALITY ? 2 * cardMax : BITSET_BYTES;
1514
+ return 2 + 4 * steps >= plainMax;
1515
+ }
1516
+ function walksRunIds(runs, count) {
1517
+ return runs.kind === RUN2 && !expandsRunSteps(runs, count);
1518
+ }
1519
+ function orRunArrayExpand(runs, array, keep) {
1520
+ const words = toWords(runs);
1521
+ const v = lows16(array);
1522
+ let added = 0;
1169
1523
  for (let i = array.off; i < array.off + array.len; i++) {
1170
- const v = u16[i];
1171
- words[v >>> 5] = words[v >>> 5] | 1 << (v & 31);
1524
+ const value = v[i];
1525
+ const word = words[value >>> 5];
1526
+ const bit = 1 << (value & 31);
1527
+ if ((word & bit) === 0) {
1528
+ words[value >>> 5] = word | bit;
1529
+ added++;
1530
+ }
1172
1531
  }
1173
- return fromWordsCard(words, popcountWords(words));
1532
+ if (added === 0 && keep) return runs;
1533
+ return optimize(fromWordsCard(words, runs.card + added));
1534
+ }
1535
+ function orRunArray(runs, array, keep) {
1536
+ return expandsRunArray(runs, array) ? orRunArrayExpand(runs, array, keep) : orRunArrayWalk(runs, array, keep);
1537
+ }
1538
+ function orRunArrayWalk(runs, array, keep) {
1539
+ const x = lows16(runs);
1540
+ const v = lows16(array);
1541
+ const out = pairs16(2 * (runs.len + array.len));
1542
+ const runEnd = runs.off + 2 * runs.len;
1543
+ const valueEnd = array.off + array.len;
1544
+ let r = runs.off;
1545
+ let vi = array.off;
1546
+ let at = 0;
1547
+ let from = 0;
1548
+ let to = -2;
1549
+ let added = 0;
1550
+ while (vi < valueEnd) {
1551
+ const value = v[vi++];
1552
+ while (r < runEnd && x[r] <= value) {
1553
+ const start = x[r];
1554
+ const end = start + x[r + 1];
1555
+ r += 2;
1556
+ if (start <= to + 1) {
1557
+ if (end > to) to = end;
1558
+ } else {
1559
+ if (to >= 0) {
1560
+ out[at++] = from;
1561
+ out[at++] = to - from;
1562
+ }
1563
+ from = start;
1564
+ to = end;
1565
+ }
1566
+ }
1567
+ if (value <= to) continue;
1568
+ added++;
1569
+ if (value === to + 1) {
1570
+ to = value;
1571
+ } else {
1572
+ if (to >= 0) {
1573
+ out[at++] = from;
1574
+ out[at++] = to - from;
1575
+ }
1576
+ from = value;
1577
+ to = value;
1578
+ }
1579
+ }
1580
+ while (r < runEnd) {
1581
+ const start = x[r];
1582
+ const end = start + x[r + 1];
1583
+ r += 2;
1584
+ if (start <= to + 1) {
1585
+ if (end > to) to = end;
1586
+ } else {
1587
+ if (to >= 0) {
1588
+ out[at++] = from;
1589
+ out[at++] = to - from;
1590
+ }
1591
+ from = start;
1592
+ to = end;
1593
+ }
1594
+ }
1595
+ out[at++] = from;
1596
+ out[at++] = to - from;
1597
+ if (added === 0 && keep) return runs;
1598
+ return runsOrPlain(out, at >>> 1, runs.card + added, true);
1599
+ }
1600
+ function orRunIdsWalk(runs, ids, from, to) {
1601
+ const x = lows16(runs);
1602
+ const out = pairs16(2 * (runs.len + to - from));
1603
+ const runEnd = runs.off + 2 * runs.len;
1604
+ let r = runs.off;
1605
+ let vi = from;
1606
+ let at = 0;
1607
+ let start = 0;
1608
+ let last = -2;
1609
+ let added = 0;
1610
+ while (vi < to) {
1611
+ const value = ids[vi++] & 65535;
1612
+ while (r < runEnd && x[r] <= value) {
1613
+ const s = x[r];
1614
+ const end = s + x[r + 1];
1615
+ r += 2;
1616
+ if (s <= last + 1) {
1617
+ if (end > last) last = end;
1618
+ } else {
1619
+ if (last >= 0) {
1620
+ out[at++] = start;
1621
+ out[at++] = last - start;
1622
+ }
1623
+ start = s;
1624
+ last = end;
1625
+ }
1626
+ }
1627
+ if (value <= last) continue;
1628
+ added++;
1629
+ if (value === last + 1) {
1630
+ last = value;
1631
+ } else {
1632
+ if (last >= 0) {
1633
+ out[at++] = start;
1634
+ out[at++] = last - start;
1635
+ }
1636
+ start = value;
1637
+ last = value;
1638
+ }
1639
+ }
1640
+ while (r < runEnd) {
1641
+ const s = x[r];
1642
+ const end = s + x[r + 1];
1643
+ r += 2;
1644
+ if (s <= last + 1) {
1645
+ if (end > last) last = end;
1646
+ } else {
1647
+ if (last >= 0) {
1648
+ out[at++] = start;
1649
+ out[at++] = last - start;
1650
+ }
1651
+ start = s;
1652
+ last = end;
1653
+ }
1654
+ }
1655
+ out[at++] = start;
1656
+ out[at++] = last - start;
1657
+ if (added === 0) return runs;
1658
+ return runsOrPlain(out, at >>> 1, runs.card + added, true);
1174
1659
  }
1175
1660
  function containerAndNot(a, b, inPlace = false) {
1176
1661
  if (a.kind === ARRAY2) {
@@ -1186,8 +1671,7 @@ function containerAndNot(a, b, inPlace = false) {
1186
1671
  words[v >>> 5] = words[v >>> 5] & ~(1 << (v & 31));
1187
1672
  }
1188
1673
  } else if (b.kind === BITSET) {
1189
- const y = words32(b);
1190
- for (let i = 0; i < WORDS; i++) words[i] = words[i] & ~y[i];
1674
+ andNotWords(words, words, words32(b));
1191
1675
  } else {
1192
1676
  const pairs = lows16(b);
1193
1677
  for (let r = 0; r < b.len; r++) {
@@ -1197,38 +1681,583 @@ function containerAndNot(a, b, inPlace = false) {
1197
1681
  }
1198
1682
  return fromWordsCard(words, popcountWords(words));
1199
1683
  }
1200
-
1201
- // src/ts-roaring/iterator.ts
1202
- var DONE = { done: true, value: void 0 };
1203
- var BitmapIterator = class {
1204
- #keys;
1205
- #conts;
1206
- /** The container being walked, as an index into `#conts`, and its kind, storage and offset. */
1207
- #at = -1;
1208
- #kind = ARRAY2;
1209
- #u16 = new Uint16Array(0);
1210
- #words = new Uint32Array(0);
1211
- #off = 0;
1212
- /** Added to every remainder: the container's key times 65,536. */
1213
- #base = 0;
1214
- /** An array: the next index and one past the last. A run container: the next run's index and the run count. A bitset: the word index. */
1215
- #pos = 0;
1216
- #end = 0;
1217
- /** A run container: the next value and the last of the current run. A bitset: what is left of the current word. */
1218
- #next = 0;
1219
- #last = -1;
1220
- constructor(keys, conts) {
1221
- this.#keys = keys;
1222
- this.#conts = conts;
1223
- }
1224
- [Symbol.iterator]() {
1225
- return this;
1226
- }
1227
- next() {
1228
- for (; ; ) {
1229
- if (this.#kind === ARRAY2) {
1230
- if (this.#pos < this.#end) {
1231
- return { done: false, value: this.#base + this.#u16[this.#pos++] };
1684
+ function xorArrays(a, b) {
1685
+ const x = lows16(a);
1686
+ const y = lows16(b);
1687
+ const ie = a.off + a.len;
1688
+ const je = b.off + b.len;
1689
+ const out = values16(a.len + b.len);
1690
+ let n = 0;
1691
+ let i = a.off;
1692
+ let j = b.off;
1693
+ while (i < ie && j < je) {
1694
+ const p = x[i];
1695
+ const q = y[j];
1696
+ out[n] = p < q ? p : q;
1697
+ n += p === q ? 0 : 1;
1698
+ i += p <= q ? 1 : 0;
1699
+ j += p >= q ? 1 : 0;
1700
+ }
1701
+ while (i < ie) out[n++] = x[i++];
1702
+ while (j < je) out[n++] = y[j++];
1703
+ if (n <= ARRAY_MAX_CARDINALITY) return arrayOfScratch(out, n);
1704
+ const words = new Uint32Array(WORDS);
1705
+ for (let k = 0; k < n; k++) {
1706
+ const v = out[k];
1707
+ words[v >>> 5] = words[v >>> 5] | 1 << (v & 31);
1708
+ }
1709
+ return bitsetContainer(words, n);
1710
+ }
1711
+ function xorRuns(a, b) {
1712
+ const x = lows16(a);
1713
+ const y = lows16(b);
1714
+ const na = 2 * a.len;
1715
+ const nb = 2 * b.len;
1716
+ const out = pairs16(2 * (a.len + b.len));
1717
+ const NONE = 2147483647;
1718
+ let i = 0;
1719
+ let j = 0;
1720
+ let pa = na > 0 ? boundary(x, a.off, 0) : NONE;
1721
+ let pb = nb > 0 ? boundary(y, b.off, 0) : NONE;
1722
+ let open = -1;
1723
+ let runs = 0;
1724
+ let card = 0;
1725
+ while (i < na || j < nb) {
1726
+ let p;
1727
+ if (pa === pb) {
1728
+ i++;
1729
+ j++;
1730
+ pa = i < na ? boundary(x, a.off, i) : NONE;
1731
+ pb = j < nb ? boundary(y, b.off, j) : NONE;
1732
+ continue;
1733
+ }
1734
+ if (pa < pb) {
1735
+ p = pa;
1736
+ i++;
1737
+ pa = i < na ? boundary(x, a.off, i) : NONE;
1738
+ } else {
1739
+ p = pb;
1740
+ j++;
1741
+ pb = j < nb ? boundary(y, b.off, j) : NONE;
1742
+ }
1743
+ if (open < 0) {
1744
+ open = p;
1745
+ } else {
1746
+ out[2 * runs] = open;
1747
+ out[2 * runs + 1] = p - 1 - open;
1748
+ runs++;
1749
+ card += p - open;
1750
+ open = -1;
1751
+ }
1752
+ }
1753
+ return card === 0 ? null : runsOrPlain(out, runs, card, true);
1754
+ }
1755
+ function boundary(u16, off, k) {
1756
+ const at = off + (k & ~1);
1757
+ return u16[at] + ((k & 1) === 0 ? 0 : u16[at + 1] + 1);
1758
+ }
1759
+ function containerXor(a, b, inPlace = false) {
1760
+ if (a.kind === BITSET || b.kind === BITSET) {
1761
+ const base = a.kind === BITSET ? a : b;
1762
+ const other = base === a ? b : a;
1763
+ if (other.kind === BITSET) {
1764
+ const x = words32(a);
1765
+ const y = words32(b);
1766
+ const out = inPlace ? x : new Uint32Array(WORDS);
1767
+ xorWords(out, x, y);
1768
+ return fromWordsCard(out, popcountWords(out));
1769
+ }
1770
+ const words2 = inPlace && base === a ? words32(base) : words32(base).slice();
1771
+ if (other.kind === ARRAY2) {
1772
+ return fromWordsCard(words2, flipValues(words2, other, base.card));
1773
+ }
1774
+ const pairs = lows16(other);
1775
+ for (let r = 0; r < other.len; r++) {
1776
+ const start = pairs[other.off + 2 * r];
1777
+ flipRange(words2, start, start + pairs[other.off + 2 * r + 1]);
1778
+ }
1779
+ return fromWordsCard(words2, popcountWords(words2));
1780
+ }
1781
+ if (a.kind === ARRAY2 && b.kind === ARRAY2) return xorArrays(a, b);
1782
+ if (a.kind === RUN2 && b.kind === RUN2) return xorRuns(a, b);
1783
+ const runs = a.kind === RUN2 ? a : b;
1784
+ const array = runs === a ? b : a;
1785
+ const words = toWords(runs);
1786
+ return fromWordsCard(words, flipValues(words, array, runs.card));
1787
+ }
1788
+ function flipValues(words, array, card) {
1789
+ const u16 = lows16(array);
1790
+ let n = card;
1791
+ for (let i = array.off; i < array.off + array.len; i++) {
1792
+ const v = u16[i];
1793
+ const w = words[v >>> 5];
1794
+ words[v >>> 5] = w ^ 1 << (v & 31);
1795
+ n += 1 - 2 * (w >>> (v & 31) & 1);
1796
+ }
1797
+ return n;
1798
+ }
1799
+ function bitsInRange(words, start, end) {
1800
+ const first = start >>> 5;
1801
+ const last = end >>> 5;
1802
+ const head = 4294967295 << (start & 31) >>> 0;
1803
+ const tail = 4294967295 >>> 31 - (end & 31);
1804
+ if (first === last) return popcount32(words[first] & head & tail);
1805
+ let n = popcount32(words[first] & head) + popcount32(words[last] & tail);
1806
+ for (let i = first + 1; i < last; i++) n += popcount32(words[i]);
1807
+ return n;
1808
+ }
1809
+ function andCountArrays(a, b) {
1810
+ const small = a.len <= b.len ? a : b;
1811
+ const big = small === a ? b : a;
1812
+ const s = lows16(small);
1813
+ const l = lows16(big);
1814
+ const se = small.off + small.len;
1815
+ const le = big.off + big.len;
1816
+ let n = 0;
1817
+ if (skewed(small.len, big.len)) {
1818
+ let at = big.off;
1819
+ for (let i2 = small.off; i2 < se; i2++) {
1820
+ const v = s[i2];
1821
+ at = gallop(l, 0, at, le, v);
1822
+ if (at === le) break;
1823
+ if (l[at] === v) n++;
1824
+ }
1825
+ return n;
1826
+ }
1827
+ if (small.len >= PROBE_MIN) {
1828
+ const first = s[small.off];
1829
+ const last = s[se - 1];
1830
+ if (last < l[big.off] || first > l[le - 1]) return 0;
1831
+ const from = gallop(l, 0, big.off, le, first);
1832
+ const to = gallop(l, 0, from, le, last + 1);
1833
+ const words = probeWords;
1834
+ for (let i2 = small.off; i2 < se; i2++) {
1835
+ const v = s[i2];
1836
+ words[v >>> 5] = words[v >>> 5] | 1 << (v & 31);
1837
+ }
1838
+ for (let j2 = from; j2 < to; j2++) {
1839
+ const v = l[j2];
1840
+ n += words[v >>> 5] >>> (v & 31) & 1;
1841
+ }
1842
+ for (let i2 = small.off; i2 < se; i2++) words[s[i2] >>> 5] = 0;
1843
+ return n;
1844
+ }
1845
+ let i = small.off;
1846
+ let j = big.off;
1847
+ while (i < se && j < le) {
1848
+ const x = s[i];
1849
+ const y = l[j];
1850
+ n += x === y ? 1 : 0;
1851
+ i += x <= y ? 1 : 0;
1852
+ j += x >= y ? 1 : 0;
1853
+ }
1854
+ return n;
1855
+ }
1856
+ function andCountArrayBitset(a, b) {
1857
+ const u16 = lows16(a);
1858
+ const words = words32(b);
1859
+ let n = 0;
1860
+ for (let i = a.off; i < a.off + a.len; i++) {
1861
+ const v = u16[i];
1862
+ n += words[v >>> 5] >>> (v & 31) & 1;
1863
+ }
1864
+ return n;
1865
+ }
1866
+ function andCountArrayRuns(a, b) {
1867
+ const u16 = lows16(a);
1868
+ const pairs = lows16(b);
1869
+ const ae = a.off + a.len;
1870
+ let n = 0;
1871
+ if (skewed(a.len, b.len)) {
1872
+ for (let i2 = a.off; i2 < ae; i2++) {
1873
+ const v = u16[i2];
1874
+ const after = lowerBound(pairs, b.off, b.len, v + 1, 2);
1875
+ if (after === 0) continue;
1876
+ const r = b.off + 2 * (after - 1);
1877
+ if (v <= pairs[r] + pairs[r + 1]) n++;
1878
+ }
1879
+ return n;
1880
+ }
1881
+ let i = a.off;
1882
+ for (let r = 0; r < b.len && i < ae; r++) {
1883
+ const start = pairs[b.off + 2 * r];
1884
+ const end = start + pairs[b.off + 2 * r + 1];
1885
+ while (i < ae && u16[i] < start) i++;
1886
+ while (i < ae && u16[i] <= end) {
1887
+ n++;
1888
+ i++;
1889
+ }
1890
+ }
1891
+ return n;
1892
+ }
1893
+ function andCountBitsetRuns(a, b) {
1894
+ const words = words32(a);
1895
+ const pairs = lows16(b);
1896
+ let n = 0;
1897
+ for (let r = 0; r < b.len; r++) {
1898
+ const start = pairs[b.off + 2 * r];
1899
+ n += bitsInRange(words, start, start + pairs[b.off + 2 * r + 1]);
1900
+ }
1901
+ return n;
1902
+ }
1903
+ function andCountRuns(a, b) {
1904
+ const x = lows16(a);
1905
+ const y = lows16(b);
1906
+ let n = 0;
1907
+ let i = 0;
1908
+ let j = 0;
1909
+ while (i < a.len && j < b.len) {
1910
+ const as = x[a.off + 2 * i];
1911
+ const ae = as + x[a.off + 2 * i + 1];
1912
+ const bs = y[b.off + 2 * j];
1913
+ const be = bs + y[b.off + 2 * j + 1];
1914
+ const lo = as > bs ? as : bs;
1915
+ const hi = ae < be ? ae : be;
1916
+ if (lo <= hi) n += hi - lo + 1;
1917
+ if (ae < be) i++;
1918
+ else j++;
1919
+ }
1920
+ return n;
1921
+ }
1922
+ function containerAndCard(a, b) {
1923
+ if (a.kind === BITSET && b.kind === BITSET) {
1924
+ return popcountAnd(words32(a), words32(b));
1925
+ }
1926
+ if (a.kind > b.kind) return containerAndCard(b, a);
1927
+ if (a.kind === ARRAY2) {
1928
+ if (b.kind === ARRAY2) return andCountArrays(a, b);
1929
+ return b.kind === BITSET ? andCountArrayBitset(a, b) : andCountArrayRuns(a, b);
1930
+ }
1931
+ return b.kind === RUN2 && a.kind === RUN2 ? andCountRuns(a, b) : andCountBitsetRuns(a, b);
1932
+ }
1933
+ function anyBitInRange(words, start, end) {
1934
+ const first = start >>> 5;
1935
+ const last = end >>> 5;
1936
+ const head = 4294967295 << (start & 31) >>> 0;
1937
+ const tail = 4294967295 >>> 31 - (end & 31);
1938
+ if (first === last) return (words[first] & head & tail) !== 0;
1939
+ if ((words[first] & head) !== 0 || (words[last] & tail) !== 0)
1940
+ return true;
1941
+ for (let i = first + 1; i < last; i++) if (words[i] !== 0) return true;
1942
+ return false;
1943
+ }
1944
+ function allBitsInRange(words, start, end) {
1945
+ const first = start >>> 5;
1946
+ const last = end >>> 5;
1947
+ const head = 4294967295 << (start & 31) >>> 0;
1948
+ const tail = 4294967295 >>> 31 - (end & 31);
1949
+ if (first === last) return (~words[first] & head & tail) === 0;
1950
+ if ((~words[first] & head) !== 0 || (~words[last] & tail) !== 0)
1951
+ return false;
1952
+ for (let i = first + 1; i < last; i++) if (words[i] !== 4294967295) return false;
1953
+ return true;
1954
+ }
1955
+ function subsetArrays(a, b) {
1956
+ const x = lows16(a);
1957
+ const y = lows16(b);
1958
+ const ie = a.off + a.len;
1959
+ const je = b.off + b.len;
1960
+ let j = b.off;
1961
+ if (skewed(a.len, b.len)) {
1962
+ for (let i2 = a.off; i2 < ie; i2++) {
1963
+ const v = x[i2];
1964
+ j = gallop(y, 0, j, je, v);
1965
+ if (j === je || y[j] !== v) return false;
1966
+ }
1967
+ return true;
1968
+ }
1969
+ let i = a.off;
1970
+ while (i < ie && j < je) {
1971
+ const p = x[i];
1972
+ const q = y[j];
1973
+ if (p < q) return false;
1974
+ i += p === q ? 1 : 0;
1975
+ j++;
1976
+ }
1977
+ return i === ie;
1978
+ }
1979
+ function subsetArrayRuns(a, b) {
1980
+ const u16 = lows16(a);
1981
+ const pairs = lows16(b);
1982
+ let r = 0;
1983
+ for (let i = a.off; i < a.off + a.len; i++) {
1984
+ const v = u16[i];
1985
+ while (r < b.len && pairs[b.off + 2 * r] + pairs[b.off + 2 * r + 1] < v)
1986
+ r++;
1987
+ if (r === b.len || pairs[b.off + 2 * r] > v) return false;
1988
+ }
1989
+ return true;
1990
+ }
1991
+ function subsetRunsArray(a, b) {
1992
+ const pairs = lows16(a);
1993
+ const y = lows16(b);
1994
+ const je = b.off + b.len;
1995
+ let j = b.off;
1996
+ for (let r = 0; r < a.len; r++) {
1997
+ const start = pairs[a.off + 2 * r];
1998
+ const last = start + pairs[a.off + 2 * r + 1];
1999
+ j = gallop(y, 0, j, je, start);
2000
+ const end = j + (last - start);
2001
+ if (end >= je || y[j] !== start || y[end] !== last) return false;
2002
+ j = end + 1;
2003
+ }
2004
+ return true;
2005
+ }
2006
+ function subsetRuns(a, b) {
2007
+ const x = lows16(a);
2008
+ const y = lows16(b);
2009
+ let j = 0;
2010
+ for (let i = 0; i < a.len; i++) {
2011
+ const start = x[a.off + 2 * i];
2012
+ const last = start + x[a.off + 2 * i + 1];
2013
+ while (j < b.len && y[b.off + 2 * j] + y[b.off + 2 * j + 1] < start)
2014
+ j++;
2015
+ if (j === b.len || y[b.off + 2 * j] > start) return false;
2016
+ if (y[b.off + 2 * j] + y[b.off + 2 * j + 1] < last) return false;
2017
+ }
2018
+ return true;
2019
+ }
2020
+ function subsetBitsetRuns(a, b) {
2021
+ const words = words32(a);
2022
+ const pairs = lows16(b);
2023
+ let from = 0;
2024
+ for (let r = 0; r < b.len; r++) {
2025
+ const start = pairs[b.off + 2 * r];
2026
+ if (start > from && anyBitInRange(words, from, start - 1)) return false;
2027
+ from = start + pairs[b.off + 2 * r + 1] + 1;
2028
+ }
2029
+ return from > 65535 || !anyBitInRange(words, from, 65535);
2030
+ }
2031
+ function containersSubset(a, b) {
2032
+ if (a.card > b.card) return false;
2033
+ if (a.kind === ARRAY2) {
2034
+ if (b.kind === ARRAY2) return subsetArrays(a, b);
2035
+ if (b.kind === RUN2) return subsetArrayRuns(a, b);
2036
+ const u16 = lows16(a);
2037
+ const words2 = words32(b);
2038
+ for (let i = a.off; i < a.off + a.len; i++) {
2039
+ const v = u16[i];
2040
+ if ((words2[v >>> 5] >>> (v & 31) & 1) === 0) return false;
2041
+ }
2042
+ return true;
2043
+ }
2044
+ if (a.kind === BITSET) {
2045
+ if (b.kind === BITSET) {
2046
+ const x = words32(a);
2047
+ const y = words32(b);
2048
+ for (let i = 0; i < WORDS; i += 8) {
2049
+ const lack = x[i] & ~y[i] | x[i + 1] & ~y[i + 1] | x[i + 2] & ~y[i + 2] | x[i + 3] & ~y[i + 3] | x[i + 4] & ~y[i + 4] | x[i + 5] & ~y[i + 5] | x[i + 6] & ~y[i + 6] | x[i + 7] & ~y[i + 7];
2050
+ if (lack !== 0) return false;
2051
+ }
2052
+ return true;
2053
+ }
2054
+ if (b.kind === RUN2) return subsetBitsetRuns(a, b);
2055
+ return containerAndCard(a, b) === a.card;
2056
+ }
2057
+ if (b.kind === ARRAY2) return subsetRunsArray(a, b);
2058
+ if (b.kind === RUN2) return subsetRuns(a, b);
2059
+ const words = words32(b);
2060
+ const pairs = lows16(a);
2061
+ for (let r = 0; r < a.len; r++) {
2062
+ const start = pairs[a.off + 2 * r];
2063
+ if (!allBitsInRange(words, start, start + pairs[a.off + 2 * r + 1])) return false;
2064
+ }
2065
+ return true;
2066
+ }
2067
+ function containersEqual(a, b) {
2068
+ if (a.card !== b.card) return false;
2069
+ if (a.kind !== b.kind) return containerAndCard(a, b) === a.card;
2070
+ if (a.kind === BITSET) return equalWords(words32(a), 0, words32(b), 0, WORDS);
2071
+ if (a.len !== b.len) return false;
2072
+ const x = lows16(a);
2073
+ const y = lows16(b);
2074
+ const n = a.kind === ARRAY2 ? a.len : 2 * a.len;
2075
+ if (n < EQUAL_VIEW_MIN) {
2076
+ if (a.off === 0 && b.off === 0) return equalU16(x, 0, y, 0, n);
2077
+ return equalU16(x, a.off, y, b.off, n);
2078
+ }
2079
+ const xb = x.byteOffset + 2 * a.off;
2080
+ const yb = y.byteOffset + 2 * b.off;
2081
+ if (usesEqualView(n, xb, yb)) {
2082
+ const m = n >>> 1;
2083
+ if (!equalWords(new Uint32Array(x.buffer, xb, m), 0, new Uint32Array(y.buffer, yb, m), 0, m))
2084
+ return false;
2085
+ return (n & 1) === 0 || x[a.off + n - 1] === y[b.off + n - 1];
2086
+ }
2087
+ return equalU16(x, a.off, y, b.off, n);
2088
+ }
2089
+ var EQUAL_VIEW_MIN = 512;
2090
+ function usesEqualView(n, xb, yb) {
2091
+ return n >= EQUAL_VIEW_MIN && (xb & 3) === 0 && (yb & 3) === 0;
2092
+ }
2093
+ function equalWords(x, xo, y, yo, n) {
2094
+ let i = 0;
2095
+ for (const end = n - 7; i < end; i += 8) {
2096
+ const d = x[xo + i] ^ y[yo + i] | x[xo + i + 1] ^ y[yo + i + 1] | x[xo + i + 2] ^ y[yo + i + 2] | x[xo + i + 3] ^ y[yo + i + 3] | x[xo + i + 4] ^ y[yo + i + 4] | x[xo + i + 5] ^ y[yo + i + 5] | x[xo + i + 6] ^ y[yo + i + 6] | x[xo + i + 7] ^ y[yo + i + 7];
2097
+ if (d !== 0) return false;
2098
+ }
2099
+ for (; i < n; i++) if (x[xo + i] !== y[yo + i]) return false;
2100
+ return true;
2101
+ }
2102
+ function equalU16(x, xo, y, yo, n) {
2103
+ let i = 0;
2104
+ for (const end = n - 7; i < end; i += 8) {
2105
+ const d = x[xo + i] ^ y[yo + i] | x[xo + i + 1] ^ y[yo + i + 1] | x[xo + i + 2] ^ y[yo + i + 2] | x[xo + i + 3] ^ y[yo + i + 3] | x[xo + i + 4] ^ y[yo + i + 4] | x[xo + i + 5] ^ y[yo + i + 5] | x[xo + i + 6] ^ y[yo + i + 6] | x[xo + i + 7] ^ y[yo + i + 7];
2106
+ if (d !== 0) return false;
2107
+ }
2108
+ for (; i < n; i++) if (x[xo + i] !== y[yo + i]) return false;
2109
+ return true;
2110
+ }
2111
+ function intersectsArrays(a, b) {
2112
+ const small = a.len <= b.len ? a : b;
2113
+ const big = small === a ? b : a;
2114
+ const s = lows16(small);
2115
+ const l = lows16(big);
2116
+ const se = small.off + small.len;
2117
+ const le = big.off + big.len;
2118
+ if (s[se - 1] < l[big.off] || s[small.off] > l[le - 1]) {
2119
+ return false;
2120
+ }
2121
+ if (skewed(small.len, big.len)) {
2122
+ let at = big.off;
2123
+ for (let i2 = small.off; i2 < se; i2++) {
2124
+ const v = s[i2];
2125
+ at = gallop(l, 0, at, le, v);
2126
+ if (at === le) return false;
2127
+ if (l[at] === v) return true;
2128
+ }
2129
+ return false;
2130
+ }
2131
+ let i = small.off;
2132
+ let j = big.off;
2133
+ if (small.len >= PROBE_MIN) {
2134
+ for (let step = 0; step < MERGE_FIRST && i < se && j < le; step++) {
2135
+ const x = s[i];
2136
+ const y = l[j];
2137
+ if (x === y) return true;
2138
+ if (x < y) i++;
2139
+ else j++;
2140
+ }
2141
+ if (i === se || j === le) return false;
2142
+ const left = i;
2143
+ const from = gallop(l, 0, j, le, s[left]);
2144
+ const to = gallop(l, 0, from, le, s[se - 1] + 1);
2145
+ const words = probeWords;
2146
+ for (let k = left; k < se; k++) {
2147
+ const v = s[k];
2148
+ words[v >>> 5] = words[v >>> 5] | 1 << (v & 31);
2149
+ }
2150
+ let hit = false;
2151
+ for (let k = from; k < to; k++) {
2152
+ const v = l[k];
2153
+ if ((words[v >>> 5] >>> (v & 31) & 1) === 1) {
2154
+ hit = true;
2155
+ break;
2156
+ }
2157
+ }
2158
+ for (let k = left; k < se; k++) words[s[k] >>> 5] = 0;
2159
+ return hit;
2160
+ }
2161
+ while (i < se && j < le) {
2162
+ const x = s[i];
2163
+ const y = l[j];
2164
+ if (x === y) return true;
2165
+ if (x < y) i++;
2166
+ else j++;
2167
+ }
2168
+ return false;
2169
+ }
2170
+ function intersectsArrayRuns(a, b) {
2171
+ const u16 = lows16(a);
2172
+ const pairs = lows16(b);
2173
+ let r = 0;
2174
+ for (let i = a.off; i < a.off + a.len; i++) {
2175
+ const v = u16[i];
2176
+ while (r < b.len && pairs[b.off + 2 * r] + pairs[b.off + 2 * r + 1] < v) {
2177
+ r++;
2178
+ }
2179
+ if (r === b.len) return false;
2180
+ if (pairs[b.off + 2 * r] <= v) return true;
2181
+ }
2182
+ return false;
2183
+ }
2184
+ function containersIntersect(a, b) {
2185
+ if (a.kind > b.kind) return containersIntersect(b, a);
2186
+ if (a.kind === ARRAY2) {
2187
+ if (b.kind === ARRAY2) return intersectsArrays(a, b);
2188
+ if (b.kind === RUN2) return intersectsArrayRuns(a, b);
2189
+ const u16 = lows16(a);
2190
+ const words = words32(b);
2191
+ for (let i2 = a.off; i2 < a.off + a.len; i2++) {
2192
+ const v = u16[i2];
2193
+ if ((words[v >>> 5] >>> (v & 31) & 1) === 1) return true;
2194
+ }
2195
+ return false;
2196
+ }
2197
+ if (a.kind === BITSET) {
2198
+ const x2 = words32(a);
2199
+ if (b.kind === BITSET) {
2200
+ const y2 = words32(b);
2201
+ for (let i2 = 0; i2 < WORDS; i2 += 8) {
2202
+ const both = x2[i2] & y2[i2] | x2[i2 + 1] & y2[i2 + 1] | x2[i2 + 2] & y2[i2 + 2] | x2[i2 + 3] & y2[i2 + 3] | x2[i2 + 4] & y2[i2 + 4] | x2[i2 + 5] & y2[i2 + 5] | x2[i2 + 6] & y2[i2 + 6] | x2[i2 + 7] & y2[i2 + 7];
2203
+ if (both !== 0) return true;
2204
+ }
2205
+ return false;
2206
+ }
2207
+ const pairs = lows16(b);
2208
+ for (let r = 0; r < b.len; r++) {
2209
+ const start = pairs[b.off + 2 * r];
2210
+ if (anyBitInRange(x2, start, start + pairs[b.off + 2 * r + 1])) return true;
2211
+ }
2212
+ return false;
2213
+ }
2214
+ const x = lows16(a);
2215
+ const y = lows16(b);
2216
+ let i = 0;
2217
+ let j = 0;
2218
+ while (i < a.len && j < b.len) {
2219
+ const as = x[a.off + 2 * i];
2220
+ const ae = as + x[a.off + 2 * i + 1];
2221
+ const bs = y[b.off + 2 * j];
2222
+ const be = bs + y[b.off + 2 * j + 1];
2223
+ if ((as > bs ? as : bs) <= (ae < be ? ae : be)) return true;
2224
+ if (ae < be) i++;
2225
+ else j++;
2226
+ }
2227
+ return false;
2228
+ }
2229
+
2230
+ // src/ts-roaring/iterator.ts
2231
+ var DONE = { done: true, value: void 0 };
2232
+ var BitmapIterator = class {
2233
+ #keys;
2234
+ #conts;
2235
+ /** The container being walked, as an index into `#conts`, and its kind, storage and offset. */
2236
+ #at = -1;
2237
+ #kind = ARRAY2;
2238
+ #u16 = new Uint16Array(0);
2239
+ #words = new Uint32Array(0);
2240
+ #off = 0;
2241
+ /** Added to every remainder: the container's key times 65,536. */
2242
+ #base = 0;
2243
+ /** An array: the next index and one past the last. A run container: the next run's index and the run count. A bitset: the word index. */
2244
+ #pos = 0;
2245
+ #end = 0;
2246
+ /** A run container: the next value and the last of the current run. A bitset: what is left of the current word. */
2247
+ #next = 0;
2248
+ #last = -1;
2249
+ constructor(keys, conts) {
2250
+ this.#keys = keys;
2251
+ this.#conts = conts;
2252
+ }
2253
+ [Symbol.iterator]() {
2254
+ return this;
2255
+ }
2256
+ next() {
2257
+ for (; ; ) {
2258
+ if (this.#kind === ARRAY2) {
2259
+ if (this.#pos < this.#end) {
2260
+ return { done: false, value: this.#base + this.#u16[this.#pos++] };
1232
2261
  }
1233
2262
  } else if (this.#kind === BITSET) {
1234
2263
  let w = this.#next;
@@ -1292,7 +2321,16 @@ function bodySize(c) {
1292
2321
  if (c.kind === BITSET) return BITSET_BYTES;
1293
2322
  return 2 + 4 * c.len;
1294
2323
  }
2324
+ var SMALL_BODY = 64;
1295
2325
  function putU16s(out, at, src, from, count) {
2326
+ if (count < SMALL_BODY) {
2327
+ for (let i = 0; i < count; i++) {
2328
+ const v = src[from + i];
2329
+ out[at++] = v & 255;
2330
+ out[at++] = v >>> 8;
2331
+ }
2332
+ return;
2333
+ }
1296
2334
  if (LITTLE_ENDIAN) {
1297
2335
  out.set(new Uint8Array(src.buffer, src.byteOffset + 2 * from, 2 * count), at);
1298
2336
  return;
@@ -1347,7 +2385,7 @@ function serializeContainers(keys, conts) {
1347
2385
  }
1348
2386
  return out;
1349
2387
  }
1350
- function decodeContainers(input) {
2388
+ function decodeContainers(input, detached = false) {
1351
2389
  const bytes = Uint8Array.prototype.slice.call(input);
1352
2390
  const layout = parsePortableLayout(bytes);
1353
2391
  const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
@@ -1357,18 +2395,21 @@ function decodeContainers(input) {
1357
2395
  let end = bytes.byteLength === 0 ? 0 : 8;
1358
2396
  let slabLength = 0;
1359
2397
  let small = 0;
1360
- for (const { cardinality, kind, offset } of layout) {
1361
- if (kind === ARRAY) {
1362
- slabLength += cardinality;
1363
- small++;
1364
- } else if (kind !== BITMAP) {
1365
- slabLength += 2 * view.getUint16(offset, true);
1366
- small++;
2398
+ if (!detached) {
2399
+ for (const { cardinality, kind, offset } of layout) {
2400
+ if (kind === ARRAY) {
2401
+ slabLength += cardinality;
2402
+ small++;
2403
+ } else if (kind !== BITMAP) {
2404
+ slabLength += 2 * view.getUint16(offset, true);
2405
+ small++;
2406
+ }
1367
2407
  }
1368
2408
  }
1369
2409
  const own = LITTLE_ENDIAN && bytes.byteOffset === 0 && bytes.buffer instanceof ArrayBuffer && bytes.buffer.byteLength === bytes.byteLength;
1370
- const alias = own && small === 1;
1371
- const slab = alias ? NO_U16 : new Uint16Array(slabLength);
2410
+ const alias = !detached && own && small === 1;
2411
+ const solo = alias || detached;
2412
+ const slab = solo ? NO_U16 : new Uint16Array(slabLength);
1372
2413
  let used = 0;
1373
2414
  for (const { key, cardinality, kind, offset } of layout) {
1374
2415
  keys[n] = key;
@@ -1377,22 +2418,22 @@ function decodeContainers(input) {
1377
2418
  const values = new Uint16Array(bytes.buffer, offset, cardinality);
1378
2419
  conts[n++] = new Container(ARRAY2, values, 0, cardinality, cardinality, false);
1379
2420
  } else {
1380
- const into = alias ? new Uint16Array(cardinality) : slab;
1381
- getU16s(bytes, view, offset, into, alias ? 0 : used, cardinality);
2421
+ const into = solo ? new Uint16Array(cardinality) : slab;
2422
+ getU16s(bytes, view, offset, into, solo ? 0 : used, cardinality);
1382
2423
  conts[n++] = new Container(
1383
2424
  ARRAY2,
1384
2425
  into,
1385
- alias ? 0 : used,
2426
+ solo ? 0 : used,
1386
2427
  cardinality,
1387
2428
  cardinality,
1388
- small > 1
2429
+ !solo && small > 1
1389
2430
  );
1390
2431
  used += cardinality;
1391
2432
  }
1392
2433
  end = offset + 2 * cardinality;
1393
2434
  } else if (kind === BITMAP) {
1394
2435
  let words;
1395
- if (own && offset % 4 === 0) {
2436
+ if (!detached && own && offset % 4 === 0) {
1396
2437
  words = new Uint32Array(bytes.buffer, offset, WORDS);
1397
2438
  } else {
1398
2439
  words = new Uint32Array(WORDS);
@@ -1410,9 +2451,16 @@ function decodeContainers(input) {
1410
2451
  const pairs = new Uint16Array(bytes.buffer, offset + 2, 2 * runs);
1411
2452
  conts[n++] = new Container(RUN2, pairs, 0, runs, cardinality, false);
1412
2453
  } else {
1413
- const into = alias ? new Uint16Array(2 * runs) : slab;
1414
- getU16s(bytes, view, offset + 2, into, alias ? 0 : used, 2 * runs);
1415
- conts[n++] = new Container(RUN2, into, alias ? 0 : used, runs, cardinality, small > 1);
2454
+ const into = solo ? new Uint16Array(2 * runs) : slab;
2455
+ getU16s(bytes, view, offset + 2, into, solo ? 0 : used, 2 * runs);
2456
+ conts[n++] = new Container(
2457
+ RUN2,
2458
+ into,
2459
+ solo ? 0 : used,
2460
+ runs,
2461
+ cardinality,
2462
+ !solo && small > 1
2463
+ );
1416
2464
  used += 2 * runs;
1417
2465
  }
1418
2466
  end = offset + 2 + 4 * runs;
@@ -1439,11 +2487,8 @@ var MAX_ID = 4294967295;
1439
2487
  function isId(value) {
1440
2488
  return Number.isInteger(value) && value >= 0 && value <= MAX_ID;
1441
2489
  }
1442
- function badId(value) {
1443
- return new ValidationError2(`${String(value)} is not an integer from 0 to ${MAX_ID}`);
1444
- }
1445
2490
  function checkedId(value) {
1446
- if (!isId(value)) throw badId(value);
2491
+ if (!isId(value)) throw refusalOfId(value);
1447
2492
  return value;
1448
2493
  }
1449
2494
  function collect(values) {
@@ -1451,10 +2496,17 @@ function collect(values) {
1451
2496
  if (Array.isArray(values)) {
1452
2497
  const list = values;
1453
2498
  const out2 = new Uint32Array(list.length);
1454
- for (let i = 0; i < list.length; i++) {
2499
+ let i = 0;
2500
+ try {
2501
+ for (; i < list.length; i++) {
2502
+ const v = list[i];
2503
+ if (v >>> 0 !== v) throw refusalOfId(v);
2504
+ out2[i] = v;
2505
+ }
2506
+ } catch (error) {
1455
2507
  const v = list[i];
1456
- if (v >>> 0 !== v) throw badId(v);
1457
- out2[i] = v;
2508
+ if (typeof v !== "number") throw refusalOfId(v);
2509
+ throw error;
1458
2510
  }
1459
2511
  return out2;
1460
2512
  }
@@ -1471,6 +2523,7 @@ function collect(values) {
1471
2523
  return out.subarray(0, n);
1472
2524
  }
1473
2525
  function collectLenient(values) {
2526
+ if (values instanceof Uint32Array) return values.slice();
1474
2527
  const list = Array.isArray(values) ? values : Array.from(values);
1475
2528
  const out = new Uint32Array(list.length);
1476
2529
  let n = 0;
@@ -1480,6 +2533,11 @@ function collectLenient(values) {
1480
2533
  }
1481
2534
  return out.subarray(0, n);
1482
2535
  }
2536
+ var FEW_IDS = 4;
2537
+ function groupPath(before, count) {
2538
+ if (count <= FEW_IDS) return "few";
2539
+ return walksRunIds(before, count) ? "walk" : "merge";
2540
+ }
1483
2541
  function sortedIds(ids, owned) {
1484
2542
  for (let i = 1; i < ids.length; i++) {
1485
2543
  if (ids[i - 1] > ids[i]) return (owned ? ids : ids.slice()).sort();
@@ -1520,9 +2578,11 @@ function lowerBoundIn(keys, key, from, to) {
1520
2578
  var OR = 0;
1521
2579
  var AND = 1;
1522
2580
  var AND_NOT = 2;
2581
+ var XOR = 3;
1523
2582
  function combineContainers(op, a, b) {
1524
- if (op === OR) return containerOr(a, b, !a.shared);
2583
+ if (op === OR) return containerOr(a, b, !a.shared || a.kind === RUN2);
1525
2584
  if (op === AND) return containerAnd(a, b, !a.shared);
2585
+ if (op === XOR) return containerXor(a, b, !a.shared);
1526
2586
  return containerAndNot(a, b, !a.shared);
1527
2587
  }
1528
2588
  var TsBitmap = class _TsBitmap {
@@ -1544,7 +2604,9 @@ var TsBitmap = class _TsBitmap {
1544
2604
  }
1545
2605
  /**
1546
2606
  * Cap the size, check the structure, then build the containers. With `whole`, bytes after the last container are
1547
- * refused too; without it they are ignored.
2607
+ * refused too; without it they are ignored. With `detached`, every container gets storage of its own, copied out of
2608
+ * the input, so nothing the result holds is a view of one shared buffer: a bitmap that is kept and then reduced
2609
+ * does not keep the whole input alive.
1548
2610
  *
1549
2611
  * @throws {IntegrityError} if the input exceeds `maxBytes`, is not a well-formed portable bitmap, or (with `whole`)
1550
2612
  * has bytes after it.
@@ -1553,7 +2615,7 @@ var TsBitmap = class _TsBitmap {
1553
2615
  if (bytes.length > maxBytes) {
1554
2616
  throw new IntegrityError3(`serialized bitmap is ${bytes.length}B, exceeds cap ${maxBytes}B`);
1555
2617
  }
1556
- const { keys, conts, end } = decodeContainers(bytes);
2618
+ const { keys, conts, end } = decodeContainers(bytes, options.detached === true);
1557
2619
  if (options.whole === true && end !== bytes.byteLength) {
1558
2620
  throw trailingBytes(bytes.byteLength, end);
1559
2621
  }
@@ -1569,6 +2631,12 @@ var TsBitmap = class _TsBitmap {
1569
2631
  const conts = this.#conts;
1570
2632
  for (let i = 0; i < conts.length; i++) conts[i] = optimize(conts[i]);
1571
2633
  }
2634
+ /** Whether at least one container is held as runs. */
2635
+ hasRunContainer() {
2636
+ for (let i = 0; i < this.#conts.length; i++)
2637
+ if (this.#conts[i].kind === RUN2) return true;
2638
+ return false;
2639
+ }
1572
2640
  /**
1573
2641
  * The set as storage chunks: each payload is the portable bytes of a one-container bitmap holding that chunk's low 16
1574
2642
  * bits, optimized the way {@link optimize} does. Nothing is built until a chunk is asked for, so a writer that yields
@@ -1593,6 +2661,11 @@ var TsBitmap = class _TsBitmap {
1593
2661
  }
1594
2662
  };
1595
2663
  }
2664
+ /** The smallest id, or `undefined` when the bitmap is empty. */
2665
+ minimum() {
2666
+ if (this.#conts.length === 0) return void 0;
2667
+ return this.#keys[0] * 65536 + containerMin(this.#conts[0]);
2668
+ }
1596
2669
  maximum() {
1597
2670
  const last = this.#conts.length - 1;
1598
2671
  if (last < 0) return void 0;
@@ -1626,36 +2699,50 @@ var TsBitmap = class _TsBitmap {
1626
2699
  const key = ids[i] >>> 16;
1627
2700
  let end = i + 1;
1628
2701
  while (end < ids.length && ids[end] >>> 16 === key) end++;
1629
- const group = fromSortedIds(ids, i, end);
2702
+ const first = i;
1630
2703
  i = end;
1631
2704
  at = gallopKeys(this.#keys, key, at);
1632
2705
  if (this.#keys[at] === key) {
1633
2706
  const before = this.#conts[at];
1634
- const after = containerOr(before, group, !before.shared);
2707
+ const path = groupPath(before, end - first);
2708
+ const after = path === "few" ? containerAddSorted(before, ids, first, end) : path === "walk" ? orRunIdsWalk(before, ids, first, end) : containerOr(
2709
+ before,
2710
+ fromSortedIds(ids, first, end),
2711
+ !before.shared || before.kind === RUN2
2712
+ );
1635
2713
  this.#conts[at] = after;
1636
2714
  this.#size += after.card - before.card;
1637
2715
  } else {
2716
+ const group = fromSortedIds(ids, first, end);
1638
2717
  fresh.push({ key, group });
1639
2718
  this.#size += group.card;
1640
2719
  }
1641
2720
  }
1642
2721
  if (fresh.length > 0) this.#insertAll(fresh);
1643
2722
  }
2723
+ /** Remove the id (anything that is not an id is ignored); whether it was there. */
1644
2724
  remove(value) {
1645
- if (!isId(value)) return;
2725
+ if (!isId(value)) return false;
1646
2726
  const key = value >>> 16;
1647
2727
  const at = lowerBound2(this.#keys, key);
1648
- if (this.#keys[at] !== key) return;
2728
+ if (this.#keys[at] !== key) return false;
1649
2729
  const before = this.#conts[at];
1650
2730
  const after = containerRemove(before, value & 65535);
1651
2731
  if (after === null) {
1652
2732
  this.#keys.splice(at, 1);
1653
2733
  this.#conts.splice(at, 1);
1654
2734
  this.#size -= before.card;
1655
- return;
2735
+ return true;
1656
2736
  }
1657
2737
  this.#conts[at] = after;
1658
2738
  this.#size += after.card - before.card;
2739
+ return after.card !== before.card;
2740
+ }
2741
+ /** Remove every id. Containers a clone shares are left to it. */
2742
+ clear() {
2743
+ this.#keys = [];
2744
+ this.#conts = [];
2745
+ this.#size = 0;
1659
2746
  }
1660
2747
  /** Remove the ids (anything that is not an id is ignored), grouped by key; the keys left empty go in one pass. */
1661
2748
  removeMany(values) {
@@ -1715,6 +2802,90 @@ var TsBitmap = class _TsBitmap {
1715
2802
  andNotInPlace(other) {
1716
2803
  this.#combine(_TsBitmap.#of(other), AND_NOT);
1717
2804
  }
2805
+ /** Flip the ids `other` holds, in one pass over the pair of each key. */
2806
+ xorInPlace(other) {
2807
+ this.#combine(_TsBitmap.#of(other), XOR);
2808
+ }
2809
+ /** How many ids both bitmaps hold, counted without building the intersection. */
2810
+ andCardinality(other) {
2811
+ const that = _TsBitmap.#of(other);
2812
+ const a = this.#keys;
2813
+ const b = that.#keys;
2814
+ let n = 0;
2815
+ let i = 0;
2816
+ let j = 0;
2817
+ while (i < a.length && j < b.length) {
2818
+ const ka = a[i];
2819
+ const kb = b[j];
2820
+ if (ka === kb) {
2821
+ n += containerAndCard(this.#conts[i++], that.#conts[j++]);
2822
+ } else if (ka < kb) {
2823
+ i = gallopKeys(a, kb, i + 1);
2824
+ } else {
2825
+ j = gallopKeys(b, ka, j + 1);
2826
+ }
2827
+ }
2828
+ return n;
2829
+ }
2830
+ /** How many ids either bitmap holds. */
2831
+ orCardinality(other) {
2832
+ return this.#size + _TsBitmap.#of(other).#size - this.andCardinality(other);
2833
+ }
2834
+ /** How many ids exactly one of the bitmaps holds. */
2835
+ xorCardinality(other) {
2836
+ return this.#size + _TsBitmap.#of(other).#size - 2 * this.andCardinality(other);
2837
+ }
2838
+ /** How many ids this bitmap holds that `other` lacks. */
2839
+ andNotCardinality(other) {
2840
+ return this.#size - this.andCardinality(other);
2841
+ }
2842
+ /** Whether the bitmaps share an id; stops at the first one found. */
2843
+ intersects(other) {
2844
+ const that = _TsBitmap.#of(other);
2845
+ const a = this.#keys;
2846
+ const b = that.#keys;
2847
+ let i = 0;
2848
+ let j = 0;
2849
+ while (i < a.length && j < b.length) {
2850
+ const ka = a[i];
2851
+ const kb = b[j];
2852
+ if (ka === kb) {
2853
+ if (containersIntersect(this.#conts[i++], that.#conts[j++])) {
2854
+ return true;
2855
+ }
2856
+ } else if (ka < kb) {
2857
+ i = gallopKeys(a, kb, i + 1);
2858
+ } else {
2859
+ j = gallopKeys(b, ka, j + 1);
2860
+ }
2861
+ }
2862
+ return false;
2863
+ }
2864
+ /** Whether every id of this bitmap is in `other`; stops at the first container that is not inside its partner. */
2865
+ isSubset(other) {
2866
+ const that = _TsBitmap.#of(other);
2867
+ if (this.#size > that.#size) return false;
2868
+ const a = this.#keys;
2869
+ const b = that.#keys;
2870
+ let j = 0;
2871
+ for (let i = 0; i < a.length; i++) {
2872
+ j = gallopKeys(b, a[i], j);
2873
+ if (j === b.length || b[j] !== a[i]) return false;
2874
+ const c = this.#conts[i];
2875
+ if (!containersSubset(c, that.#conts[j++])) return false;
2876
+ }
2877
+ return true;
2878
+ }
2879
+ /** Whether both hold the same ids, whatever the kinds of their containers. */
2880
+ isEqual(other) {
2881
+ const that = _TsBitmap.#of(other);
2882
+ if (this.#size !== that.#size || this.#keys.length !== that.#keys.length) return false;
2883
+ for (let i = 0; i < this.#keys.length; i++) {
2884
+ if (this.#keys[i] !== that.#keys[i]) return false;
2885
+ if (!containersEqual(this.#conts[i], that.#conts[i])) return false;
2886
+ }
2887
+ return true;
2888
+ }
1718
2889
  [Symbol.iterator]() {
1719
2890
  return new BitmapIterator(this.#keys, this.#conts);
1720
2891
  }
@@ -1804,7 +2975,114 @@ var TsBitmap = class _TsBitmap {
1804
2975
  const ka = a[i];
1805
2976
  const kb = b[j];
1806
2977
  if (ka === kb) {
1807
- const c = combineContainers(op, ca[i++], cb[j++]);
2978
+ const c = combineContainers(op, ca[i++], cb[j++]);
2979
+ if (c !== null) {
2980
+ keys.push(ka);
2981
+ conts.push(c);
2982
+ size += c.card;
2983
+ }
2984
+ } else if (ka < kb) {
2985
+ if (op === AND) {
2986
+ i = gallopKeys(a, kb, i + 1);
2987
+ } else {
2988
+ keys.push(ka);
2989
+ conts.push(ca[i]);
2990
+ size += ca[i++].card;
2991
+ }
2992
+ } else if (op === AND) {
2993
+ j = gallopKeys(b, ka, j + 1);
2994
+ } else {
2995
+ if (op === OR || op === XOR) {
2996
+ keys.push(kb);
2997
+ conts.push(cloneContainer(cb[j]));
2998
+ size += cb[j].card;
2999
+ }
3000
+ j++;
3001
+ }
3002
+ }
3003
+ if (op !== AND) {
3004
+ for (; i < a.length; i++) {
3005
+ keys.push(a[i]);
3006
+ conts.push(ca[i]);
3007
+ size += ca[i].card;
3008
+ }
3009
+ }
3010
+ if (op === OR || op === XOR) {
3011
+ for (; j < b.length; j++) {
3012
+ keys.push(b[j]);
3013
+ conts.push(cloneContainer(cb[j]));
3014
+ size += cb[j].card;
3015
+ }
3016
+ }
3017
+ this.#keys = keys;
3018
+ this.#conts = conts;
3019
+ this.#size = size;
3020
+ }
3021
+ /** The ids both bitmaps hold, as a new bitmap; neither operand changes and no container of either is kept. */
3022
+ static and(a, b) {
3023
+ return _TsBitmap.#fresh(_TsBitmap.#of(a), _TsBitmap.#of(b), AND);
3024
+ }
3025
+ /** The ids either holds, as a new bitmap; neither operand changes. */
3026
+ static or(a, b) {
3027
+ return _TsBitmap.#fresh(_TsBitmap.#of(a), _TsBitmap.#of(b), OR);
3028
+ }
3029
+ /**
3030
+ * The ids any of `bitmaps` holds, as a new bitmap that owns all its storage; no operand changes and none is flagged.
3031
+ * The containers of each key are gathered across the inputs and united in one pass (see {@link orManyContainers}),
3032
+ * counted once. A key only one input holds is copied as it is, a run included.
3033
+ */
3034
+ static orMany(bitmaps) {
3035
+ const byKey = /* @__PURE__ */ new Map();
3036
+ for (const input of bitmaps) {
3037
+ const that = _TsBitmap.#of(input);
3038
+ for (let i = 0; i < that.#keys.length; i++) {
3039
+ const key = that.#keys[i];
3040
+ const held = byKey.get(key);
3041
+ if (held === void 0) byKey.set(key, [that.#conts[i]]);
3042
+ else held.push(that.#conts[i]);
3043
+ }
3044
+ }
3045
+ const keys = Array.from(byKey.keys()).sort((x, y) => x - y);
3046
+ const conts = [];
3047
+ let size = 0;
3048
+ for (const key of keys) {
3049
+ const held = byKey.get(key);
3050
+ const c = held.length === 1 ? cloneContainer(held[0]) : orManyContainers(held);
3051
+ conts.push(c);
3052
+ size += c.card;
3053
+ }
3054
+ return new _TsBitmap(keys, conts, size);
3055
+ }
3056
+ /** The ids exactly one holds, as a new bitmap; neither operand changes. */
3057
+ static xor(a, b) {
3058
+ return _TsBitmap.#fresh(_TsBitmap.#of(a), _TsBitmap.#of(b), XOR);
3059
+ }
3060
+ /** The ids of `a` that `b` lacks, as a new bitmap; neither operand changes. */
3061
+ static andNot(a, b) {
3062
+ return _TsBitmap.#fresh(_TsBitmap.#of(a), _TsBitmap.#of(b), AND_NOT);
3063
+ }
3064
+ /**
3065
+ * The same walk as {@link TsBitmap.#combine}, building a new bitmap and leaving both operands whole. Where both hold
3066
+ * a key, the pair combines into a fresh container (the in-place form is never taken, so no storage of either operand
3067
+ * is written). A container only `x` holds is kept by reference and flagged shared, so a later write to `x` or to the
3068
+ * result copies it once; for an intersection nothing of `x` is kept, so nothing is flagged. A container only `y`
3069
+ * holds is copied in for a union or a symmetric difference.
3070
+ */
3071
+ static #fresh(x, y, op) {
3072
+ const a = x.#keys;
3073
+ const b = y.#keys;
3074
+ const ca = x.#conts;
3075
+ const cb = y.#conts;
3076
+ const keys = [];
3077
+ const conts = [];
3078
+ let size = 0;
3079
+ let i = 0;
3080
+ let j = 0;
3081
+ while (i < a.length && j < b.length) {
3082
+ const ka = a[i];
3083
+ const kb = b[j];
3084
+ if (ka === kb) {
3085
+ const c = freshPair(op, ca[i++], cb[j++]);
1808
3086
  if (c !== null) {
1809
3087
  keys.push(ka);
1810
3088
  conts.push(c);
@@ -1814,14 +3092,16 @@ var TsBitmap = class _TsBitmap {
1814
3092
  if (op === AND) {
1815
3093
  i = gallopKeys(a, kb, i + 1);
1816
3094
  } else {
3095
+ const c = ca[i++];
3096
+ c.shared = true;
1817
3097
  keys.push(ka);
1818
- conts.push(ca[i]);
1819
- size += ca[i++].card;
3098
+ conts.push(c);
3099
+ size += c.card;
1820
3100
  }
1821
3101
  } else if (op === AND) {
1822
3102
  j = gallopKeys(b, ka, j + 1);
1823
3103
  } else {
1824
- if (op === OR) {
3104
+ if (op === OR || op === XOR) {
1825
3105
  keys.push(kb);
1826
3106
  conts.push(cloneContainer(cb[j]));
1827
3107
  size += cb[j].card;
@@ -1831,23 +3111,29 @@ var TsBitmap = class _TsBitmap {
1831
3111
  }
1832
3112
  if (op !== AND) {
1833
3113
  for (; i < a.length; i++) {
3114
+ const c = ca[i];
3115
+ c.shared = true;
1834
3116
  keys.push(a[i]);
1835
- conts.push(ca[i]);
1836
- size += ca[i].card;
3117
+ conts.push(c);
3118
+ size += c.card;
1837
3119
  }
1838
3120
  }
1839
- if (op === OR) {
3121
+ if (op === OR || op === XOR) {
1840
3122
  for (; j < b.length; j++) {
1841
3123
  keys.push(b[j]);
1842
3124
  conts.push(cloneContainer(cb[j]));
1843
3125
  size += cb[j].card;
1844
3126
  }
1845
3127
  }
1846
- this.#keys = keys;
1847
- this.#conts = conts;
1848
- this.#size = size;
3128
+ return new _TsBitmap(keys, conts, size);
1849
3129
  }
1850
3130
  };
3131
+ function freshPair(op, a, b) {
3132
+ if (op === OR) return containerOr(a, b, false);
3133
+ if (op === AND) return containerAnd(a, b, false);
3134
+ if (op === AND_NOT) return containerAndNot(a, b, false);
3135
+ return containerXor(a, b, false);
3136
+ }
1851
3137
  var EMPTIED = arrayContainer(new Uint16Array(0), 0);
1852
3138
  var tsRoaringCodec = {
1853
3139
  empty: () => TsBitmap.empty(),
@@ -1868,34 +3154,6 @@ var activeCodec = tsRoaringCodec;
1868
3154
  function flagshipCodec() {
1869
3155
  return activeCodec;
1870
3156
  }
1871
- var ReadonlyRoaringView = class {
1872
- #bitmap;
1873
- constructor(bitmap) {
1874
- this.#bitmap = bitmap;
1875
- }
1876
- get size() {
1877
- return this.#bitmap.size;
1878
- }
1879
- has(id) {
1880
- return this.#bitmap.has(id);
1881
- }
1882
- [Symbol.iterator]() {
1883
- return this.#bitmap[Symbol.iterator]();
1884
- }
1885
- /** The portable bytes, for exactly the argument `'portable'`; any other call is a `ValidationError`. */
1886
- serialize(...args) {
1887
- if (args.length !== 1 || args[0] !== "portable") {
1888
- const got = args.length === 0 ? "no argument" : args.map((a) => typeof a === "string" ? `'${a}'` : typeof a).join(", ");
1889
- throw new ValidationError3(
1890
- `a decoded bitmap serializes only as serialize('portable'); got ${got}`
1891
- );
1892
- }
1893
- return this.#bitmap.serialize();
1894
- }
1895
- };
1896
- function deserializePortable(bytes) {
1897
- return new ReadonlyRoaringView(decodeSerialized(bytes, flagshipCodec()));
1898
- }
1899
3157
 
1900
3158
  // src/system-clock.ts
1901
3159
  var SystemClock = class {
@@ -2035,7 +3293,7 @@ import {
2035
3293
  DEFAULT_RETRY_POLICY,
2036
3294
  NOOP_METRICS,
2037
3295
  RetryingStorageChunkSource,
2038
- ValidationError as ValidationError4,
3296
+ ValidationError as ValidationError3,
2039
3297
  isStorageBackend
2040
3298
  } from "@cloudbitmaps/core";
2041
3299
  function resolveRetryPolicy(partial) {
@@ -2059,7 +3317,7 @@ function wireStore(options, clock, rng, metrics) {
2059
3317
  if (options.retry !== false) {
2060
3318
  const { onRetry: userOnRetry, ...ov } = options.retry ?? {};
2061
3319
  if (userOnRetry !== void 0 && typeof userOnRetry !== "function") {
2062
- throw new ValidationError4("retry.onRetry must be a function");
3320
+ throw new ValidationError3("retry.onRetry must be a function");
2063
3321
  }
2064
3322
  retryOptions = {
2065
3323
  clock,
@@ -2090,7 +3348,7 @@ function wireStore(options, clock, rng, metrics) {
2090
3348
  function resolveStorageSource(options, clock) {
2091
3349
  const storage = options.storage;
2092
3350
  if (storage === null || typeof storage !== "object") {
2093
- throw new ValidationError4(
3351
+ throw new ValidationError3(
2094
3352
  "`storage` must be a StorageBackend, an IStorageDriver, or a StorageChunkSource"
2095
3353
  );
2096
3354
  }
@@ -2100,14 +3358,14 @@ function resolveStorageSource(options, clock) {
2100
3358
  const hasPutImmutable = typeof storage.putImmutable === "function";
2101
3359
  const isBackend = isStorageBackend(storage);
2102
3360
  if (isBackend && (hasGetChunk || hasPutImmutable)) {
2103
- throw new ValidationError4(
3361
+ throw new ValidationError3(
2104
3362
  `\`storage\` is a StorageBackend that also exposes ${hasGetChunk ? "`getChunk`" : "`putImmutable`"} \u2014 ambiguous. A backend must not also be a driver or a source; pass whichever one you mean.`
2105
3363
  );
2106
3364
  }
2107
3365
  const hasStorageHalf = isObject(asBackend.storage);
2108
3366
  const hasRegistryHalf = isObject(asBackend.registry);
2109
3367
  if (!isBackend && hasPutImmutable && hasRegistryHalf) {
2110
- throw new ValidationError4(
3368
+ throw new ValidationError3(
2111
3369
  "`storage` looks like a driver that also carries a `registry`. Passed as a bare driver it would have no pointer at all \u2014 generations would resolve by list-scan, so reads could serve a generation that was written but never published. If you meant a backend, use a backend class \u2014 S3Storage, GcsStorage, AzureBlobStorage, LocalFsStorage or MemoryStorage \u2014 or, to pair a driver of your own with a registry, brand the pair with `brandAsBackend` from `@cloudbitmaps/core/driver-kit`."
2112
3370
  );
2113
3371
  }
@@ -2116,11 +3374,11 @@ function resolveStorageSource(options, clock) {
2116
3374
  const registryOk = typeof asBackend.registry.compareAndSwap === "function";
2117
3375
  if (!storageOk || !registryOk) {
2118
3376
  const bad = !storageOk ? "`storage` half is not an IStorageDriver (no `putImmutable`)" : "`registry` half is not an IRegistryDriver (no `compareAndSwap`)";
2119
- throw new ValidationError4(
3377
+ throw new ValidationError3(
2120
3378
  "`storage` looks like a backend but its " + bad + " \u2014 use a backend class, or brand a pair of drivers with `brandAsBackend` from `@cloudbitmaps/core/driver-kit`."
2121
3379
  );
2122
3380
  }
2123
- throw new ValidationError4(
3381
+ throw new ValidationError3(
2124
3382
  "`storage` must be a backend \u2014 S3Storage, GcsStorage, AzureBlobStorage, LocalFsStorage or MemoryStorage. An object with `.storage` and `.registry` is not one: a backend builds both halves from a single bucket and prefix, so they cannot disagree, and hand-assembling them re-opens exactly that mismatch \u2014 a store whose pointer and generations live in different places reads as empty rather than failing. A driver author who genuinely wants halves of their own \u2014 an instrumented driver, a registry in a database you already run \u2014 brands the pair with `brandAsBackend` from `@cloudbitmaps/core/driver-kit`, which is taking on that they agree."
2125
3383
  );
2126
3384
  }
@@ -2141,18 +3399,18 @@ function resolveStorageSource(options, clock) {
2141
3399
  };
2142
3400
  }
2143
3401
  if (hasGetChunk && hasPutImmutable) {
2144
- throw new ValidationError4(
3402
+ throw new ValidationError3(
2145
3403
  "`storage` exposes both `getChunk` and `putImmutable` \u2014 ambiguous; pass a StorageBackend, an IStorageDriver, or a StorageChunkSource, not a hybrid"
2146
3404
  );
2147
3405
  }
2148
3406
  if (!hasGetChunk && !hasPutImmutable) {
2149
- throw new ValidationError4(
3407
+ throw new ValidationError3(
2150
3408
  "`storage` must be a StorageBackend, an IStorageDriver, or a StorageChunkSource"
2151
3409
  );
2152
3410
  }
2153
3411
  if (hasGetChunk) {
2154
3412
  if (options.encryption?.keystore !== void 0 || options.encryption?.required === true) {
2155
- throw new ValidationError4(
3413
+ throw new ValidationError3(
2156
3414
  "keystore/requireEncryption apply only when the store builds its own read path: a StorageChunkSource of your own reads an encrypted segment by itself, if it must; to have the store decrypt, pass a backend"
2157
3415
  );
2158
3416
  }
@@ -2174,32 +3432,32 @@ function resolveStorageSource(options, clock) {
2174
3432
  }
2175
3433
 
2176
3434
  // src/options.ts
2177
- import { ValidationError as ValidationError5 } from "@cloudbitmaps/core";
3435
+ import { ValidationError as ValidationError4 } from "@cloudbitmaps/core";
2178
3436
  var keysOf = () => (keys) => keys;
2179
3437
  var kindOf = (v) => v === null ? "null" : Array.isArray(v) ? "an array" : `a ${typeof v}`;
2180
3438
  function optionsError(options, op, known, booleans = [], misplaced = []) {
2181
3439
  if (options === void 0 || options === null) return void 0;
2182
3440
  if (typeof options !== "object" || Array.isArray(options)) {
2183
- return new ValidationError5(`${op}: options must be an object; got ${kindOf(options)}`);
3441
+ return new ValidationError4(`${op}: options must be an object; got ${kindOf(options)}`);
2184
3442
  }
2185
3443
  const bag = options;
2186
3444
  const unknown = Object.keys(bag).filter((k) => !known.includes(k) && bag[k] !== void 0);
2187
3445
  for (const k of misplaced) if (!unknown.includes(k) && bag[k] !== void 0) unknown.push(k);
2188
3446
  if (unknown.length > 0) {
2189
- return new ValidationError5(
3447
+ return new ValidationError4(
2190
3448
  `${op}: unknown option${unknown.length > 1 ? "s" : ""} ${unknown.map((k) => `"${k}"`).join(", ")}; it takes { ${known.join(", ")} }`
2191
3449
  );
2192
3450
  }
2193
3451
  const audit = bag.audit;
2194
3452
  if (audit !== void 0 && audit !== null && typeof audit.onEvent !== "function") {
2195
- return new ValidationError5(
3453
+ return new ValidationError4(
2196
3454
  `${op}: audit must be a sink with an onEvent(event) method, such as a RecordingAuditSink`
2197
3455
  );
2198
3456
  }
2199
3457
  for (const name of booleans) {
2200
3458
  const v = bag[name];
2201
3459
  if (v !== void 0 && typeof v !== "boolean") {
2202
- return new ValidationError5(`${op}: \`${name}\` must be a boolean; got ${kindOf(v)}`);
3460
+ return new ValidationError4(`${op}: \`${name}\` must be a boolean; got ${kindOf(v)}`);
2203
3461
  }
2204
3462
  }
2205
3463
  return void 0;
@@ -2220,6 +3478,407 @@ function checkOptions(options, op, known, booleans, misplaced) {
2220
3478
 
2221
3479
  // src/index.ts
2222
3480
  import { MemoryStorage, LocalFsStorage, InProcessKeystore } from "@cloudbitmaps/core/node";
3481
+
3482
+ // src/bitmap.ts
3483
+ import {
3484
+ MAX_SERIALIZED_LOAD_BYTES,
3485
+ ValidationError as ValidationError5,
3486
+ decodeSerialized,
3487
+ refusalOfId as refusalOfId2
3488
+ } from "@cloudbitmaps/core";
3489
+
3490
+ // src/count-route.ts
3491
+ var COUNT_BY_KERNELS = true;
3492
+
3493
+ // src/bitmap.ts
3494
+ function tagOf(value) {
3495
+ return Object.prototype.toString.call(value).slice(8, -1);
3496
+ }
3497
+ var VIEW = Object.getPrototypeOf(Uint8Array.prototype);
3498
+ var viewGetter = (name) => Object.getOwnPropertyDescriptor(VIEW, name)?.get;
3499
+ var bufferOf = viewGetter("buffer");
3500
+ var plainByteLength = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "byteLength")?.get;
3501
+ var hasSharedMemory = typeof SharedArrayBuffer === "function";
3502
+ function inSharedMemory(ids) {
3503
+ if (!hasSharedMemory) return false;
3504
+ try {
3505
+ plainByteLength.call(bufferOf.call(ids));
3506
+ return false;
3507
+ } catch {
3508
+ return true;
3509
+ }
3510
+ }
3511
+ function checkedId2(id) {
3512
+ if (typeof id !== "number" || id >>> 0 !== id) throw refusalOfId2(id);
3513
+ return id;
3514
+ }
3515
+ function oneIdOnly(method, bulk) {
3516
+ return new ValidationError5(`${method} takes one id; use ${bulk} for several`);
3517
+ }
3518
+ function idsOf(values) {
3519
+ if (typeof values !== "object" || values === null || !(Symbol.iterator in values)) {
3520
+ throw new ValidationError5("values must be an iterable of ids");
3521
+ }
3522
+ const tag = tagOf(values);
3523
+ if (tag === "Uint8Array" || tag === "Uint8ClampedArray") {
3524
+ throw new ValidationError5(
3525
+ `values are ids, and this is a ${tag === "Uint8Array" ? "Uint8Array or Buffer" : tag}: each byte would be read as an id. To read portable bytes, call RoaringBitmap.deserialize(bytes).`
3526
+ );
3527
+ }
3528
+ if (values instanceof Uint32Array && inSharedMemory(values)) return new Uint32Array(values);
3529
+ return values;
3530
+ }
3531
+ var detachedCodec = {
3532
+ ...tsRoaringCodec,
3533
+ safeDeserialize: (bytes, maxBytes, options) => TsBitmap.safeDeserialize(bytes, maxBytes, { ...options, detached: true })
3534
+ };
3535
+ function maxBytesOf(options) {
3536
+ if (options === void 0) return MAX_SERIALIZED_LOAD_BYTES;
3537
+ if (typeof options !== "object" || options === null) {
3538
+ throw new ValidationError5(
3539
+ `deserialize takes no format argument, the format is always portable; its second argument is { maxBytes } or nothing, not ${kindOf(options)}`
3540
+ );
3541
+ }
3542
+ checkOptions(options, "RoaringBitmap.deserialize", ["maxBytes"]);
3543
+ const { maxBytes } = picked(options, ["maxBytes"]);
3544
+ if (maxBytes === void 0) return MAX_SERIALIZED_LOAD_BYTES;
3545
+ if (!Number.isInteger(maxBytes) || maxBytes < 0 || maxBytes > MAX_SERIALIZED_LOAD_BYTES) {
3546
+ throw new ValidationError5(
3547
+ `maxBytes must be an integer from 0 to ${MAX_SERIALIZED_LOAD_BYTES}, the size no canonical bitmap exceeds`
3548
+ );
3549
+ }
3550
+ return maxBytes;
3551
+ }
3552
+ var RoaringBitmap = class _RoaringBitmap {
3553
+ #bitmap;
3554
+ /**
3555
+ * A bitmap of `values`: an array or another iterable of ids, a `Uint32Array` (read in place when it already ascends,
3556
+ * else sorted on a copy; it is never changed or kept), or another `RoaringBitmap` (a copy-on-write `clone()`).
3557
+ * With no argument it is empty.
3558
+ *
3559
+ * @throws {ValidationError} for an id that is not an integer from 0 to 4294967295; for a value that is not an
3560
+ * iterable (`null`, a number, a string, an object, an `ArrayBuffer`); and for a `Uint8Array`, `Uint8ClampedArray` or
3561
+ * `Buffer`, which would read each byte as an id: call {@link RoaringBitmap.deserialize} for bytes.
3562
+ */
3563
+ constructor(values) {
3564
+ if (values === void 0) {
3565
+ this.#bitmap = TsBitmap.empty();
3566
+ } else if (_RoaringBitmap.#is(values)) {
3567
+ this.#bitmap = values.#bitmap.clone();
3568
+ } else {
3569
+ this.#bitmap = TsBitmap.fromValues(idsOf(values));
3570
+ }
3571
+ }
3572
+ /**
3573
+ * Decode portable Roaring bytes you hold, through the check a `{ serialized }` load makes first: a size cap, a
3574
+ * structural check and one whole bitmap, and only then the decoder. The result owns its storage: it keeps nothing
3575
+ * of `bytes`, so a large input that is decoded and then reduced can be freed.
3576
+ *
3577
+ * @param bytes a `Uint8Array`, which a Node `Buffer` is.
3578
+ * @param options `{ maxBytes }` lowers the size cap below the default of 537,403,396 bytes.
3579
+ * @throws {ValidationError} for something that is not a `Uint8Array`; an empty or detached one (an empty buffer is
3580
+ * not a bitmap: `new RoaringBitmap()` is the empty set); one over the cap or `maxBytes`; bytes that are not exactly
3581
+ * one well-formed portable bitmap, including bytes after its last container; a second argument that is not
3582
+ * `undefined` or an object whose only key is `maxBytes` (a format argument such as `'portable'` is one); and a
3583
+ * `maxBytes` that is not an integer from 0 to the cap.
3584
+ */
3585
+ static deserialize(bytes, options) {
3586
+ const maxBytes = maxBytesOf(options);
3587
+ return _RoaringBitmap.#wrap(
3588
+ decodeSerialized(bytes, detachedCodec, "the buffer", {
3589
+ maxBytes,
3590
+ refuseEmpty: true
3591
+ })
3592
+ );
3593
+ }
3594
+ /** Whether `value` is a `RoaringBitmap` of this copy of the package. */
3595
+ static #is(value) {
3596
+ return typeof value === "object" && value !== null && #bitmap in value;
3597
+ }
3598
+ static #wrap(bitmap) {
3599
+ const out = new _RoaringBitmap();
3600
+ out.#bitmap = bitmap;
3601
+ return out;
3602
+ }
3603
+ /** The codec bitmap of an operand, or a refusal that says what combines with what. */
3604
+ static #operand(other) {
3605
+ if (!_RoaringBitmap.#is(other)) {
3606
+ throw new ValidationError5(
3607
+ "a RoaringBitmap combines only with another RoaringBitmap of this copy of the package"
3608
+ );
3609
+ }
3610
+ return other.#bitmap;
3611
+ }
3612
+ /** How many ids it holds. */
3613
+ get size() {
3614
+ return this.#bitmap.size;
3615
+ }
3616
+ /** Whether it holds no id. */
3617
+ get isEmpty() {
3618
+ return this.#bitmap.isEmpty;
3619
+ }
3620
+ /**
3621
+ * Whether it holds `id`.
3622
+ *
3623
+ * @throws {ValidationError} for a value that is not an integer from 0 to 4294967295.
3624
+ */
3625
+ has(id) {
3626
+ return this.#bitmap.has(checkedId2(id));
3627
+ }
3628
+ /** The smallest id, or `undefined` when it is empty. */
3629
+ minimum() {
3630
+ return this.#bitmap.minimum();
3631
+ }
3632
+ /** The largest id, or `undefined` when it is empty. */
3633
+ maximum() {
3634
+ return this.#bitmap.maximum();
3635
+ }
3636
+ /**
3637
+ * Add one id; returns this bitmap, for chaining.
3638
+ *
3639
+ * @throws {ValidationError} for a value that is not an integer from 0 to 4294967295, and for a second argument:
3640
+ * use {@link RoaringBitmap.addMany} to add several.
3641
+ */
3642
+ add(id) {
3643
+ if (arguments.length !== 1) throw oneIdOnly("add", "addMany");
3644
+ this.#bitmap.add(checkedId2(id));
3645
+ return this;
3646
+ }
3647
+ /**
3648
+ * Add every id of `values` (an iterable of ids, or a `Uint32Array`); returns this bitmap. Nothing is added if any
3649
+ * of them is refused.
3650
+ *
3651
+ * @throws {ValidationError} as the constructor does.
3652
+ */
3653
+ addMany(values) {
3654
+ if (_RoaringBitmap.#is(values)) this.#bitmap.orInPlace(values.#bitmap);
3655
+ else this.#bitmap.addMany(idsOf(values));
3656
+ return this;
3657
+ }
3658
+ /**
3659
+ * Remove one id; whether it was there.
3660
+ *
3661
+ * @throws {ValidationError} for a value that is not an integer from 0 to 4294967295, and for a second argument:
3662
+ * use {@link RoaringBitmap.removeMany} to remove several.
3663
+ */
3664
+ remove(id) {
3665
+ if (arguments.length !== 1) throw oneIdOnly("remove", "removeMany");
3666
+ return this.#bitmap.remove(checkedId2(id));
3667
+ }
3668
+ /**
3669
+ * Remove every id of `values` (an iterable of ids, or a `Uint32Array`); returns this bitmap. Nothing is removed if
3670
+ * any of them is refused.
3671
+ *
3672
+ * @throws {ValidationError} as the constructor does.
3673
+ */
3674
+ removeMany(values) {
3675
+ if (_RoaringBitmap.#is(values)) this.#bitmap.andNotInPlace(values.#bitmap);
3676
+ else this.#bitmap.removeMany(collect(idsOf(values)));
3677
+ return this;
3678
+ }
3679
+ /** Remove every id. */
3680
+ clear() {
3681
+ this.#bitmap.clear();
3682
+ }
3683
+ /**
3684
+ * A copy. It is copy-on-write: the copy costs the key list and one flag per container, not the ids, and the first
3685
+ * write to a container on either side copies that container once.
3686
+ */
3687
+ clone() {
3688
+ return _RoaringBitmap.#wrap(this.#bitmap.clone());
3689
+ }
3690
+ /**
3691
+ * Keep only the ids `other` also holds; returns this bitmap. `other` is not changed, and may be this bitmap.
3692
+ *
3693
+ * @throws {ValidationError} if `other` is not a `RoaringBitmap` of this copy of the package.
3694
+ */
3695
+ andInPlace(other) {
3696
+ this.#bitmap.andInPlace(_RoaringBitmap.#operand(other));
3697
+ return this;
3698
+ }
3699
+ /**
3700
+ * Add the ids `other` holds; returns this bitmap. `other` is not changed, and may be this bitmap.
3701
+ *
3702
+ * @throws {ValidationError} if `other` is not a `RoaringBitmap` of this copy of the package.
3703
+ */
3704
+ orInPlace(other) {
3705
+ this.#bitmap.orInPlace(_RoaringBitmap.#operand(other));
3706
+ return this;
3707
+ }
3708
+ /**
3709
+ * Remove the ids `other` holds; returns this bitmap. `other` is not changed, and may be this bitmap.
3710
+ *
3711
+ * @throws {ValidationError} if `other` is not a `RoaringBitmap` of this copy of the package.
3712
+ */
3713
+ andNotInPlace(other) {
3714
+ this.#bitmap.andNotInPlace(_RoaringBitmap.#operand(other));
3715
+ return this;
3716
+ }
3717
+ /**
3718
+ * Flip the ids `other` holds: keep those only this bitmap holds, add those only `other` holds; returns this bitmap.
3719
+ * `other` is not changed, and may be this bitmap (the result is then empty).
3720
+ *
3721
+ * @throws {ValidationError} if `other` is not a `RoaringBitmap` of this copy of the package.
3722
+ */
3723
+ xorInPlace(other) {
3724
+ this.#bitmap.xorInPlace(_RoaringBitmap.#operand(other));
3725
+ return this;
3726
+ }
3727
+ /**
3728
+ * How many ids both bitmaps hold, without building the intersection. Neither bitmap changes; `other` may be this one.
3729
+ *
3730
+ * @throws {ValidationError} if `other` is not a `RoaringBitmap` of this copy of the package.
3731
+ */
3732
+ andCardinality(other) {
3733
+ const that = _RoaringBitmap.#operand(other);
3734
+ return COUNT_BY_KERNELS ? this.#bitmap.andCardinality(that) : TsBitmap.and(this.#bitmap, that).size;
3735
+ }
3736
+ /**
3737
+ * How many ids either bitmap holds. Neither bitmap changes; `other` may be this one.
3738
+ *
3739
+ * @throws {ValidationError} if `other` is not a `RoaringBitmap` of this copy of the package.
3740
+ */
3741
+ orCardinality(other) {
3742
+ const that = _RoaringBitmap.#operand(other);
3743
+ return COUNT_BY_KERNELS ? this.#bitmap.orCardinality(that) : TsBitmap.or(this.#bitmap, that).size;
3744
+ }
3745
+ /**
3746
+ * How many ids exactly one of the bitmaps holds. Neither bitmap changes; `other` may be this one.
3747
+ *
3748
+ * @throws {ValidationError} if `other` is not a `RoaringBitmap` of this copy of the package.
3749
+ */
3750
+ xorCardinality(other) {
3751
+ const that = _RoaringBitmap.#operand(other);
3752
+ return COUNT_BY_KERNELS ? this.#bitmap.xorCardinality(that) : TsBitmap.xor(this.#bitmap, that).size;
3753
+ }
3754
+ /**
3755
+ * How many ids this bitmap holds that `other` lacks. Neither bitmap changes; `other` may be this one.
3756
+ *
3757
+ * @throws {ValidationError} if `other` is not a `RoaringBitmap` of this copy of the package.
3758
+ */
3759
+ andNotCardinality(other) {
3760
+ const that = _RoaringBitmap.#operand(other);
3761
+ return COUNT_BY_KERNELS ? this.#bitmap.andNotCardinality(that) : TsBitmap.andNot(this.#bitmap, that).size;
3762
+ }
3763
+ /**
3764
+ * Whether the bitmaps share an id. Neither bitmap changes; `other` may be this one.
3765
+ *
3766
+ * @throws {ValidationError} if `other` is not a `RoaringBitmap` of this copy of the package.
3767
+ */
3768
+ intersects(other) {
3769
+ const that = _RoaringBitmap.#operand(other);
3770
+ return COUNT_BY_KERNELS ? this.#bitmap.intersects(that) : !TsBitmap.and(this.#bitmap, that).isEmpty;
3771
+ }
3772
+ /**
3773
+ * Whether every id of this bitmap is in `other` (an empty bitmap is a subset of every bitmap, itself included). Neither
3774
+ * bitmap changes. Unlike the `roaring` package, which answers `false`, a value that is not a bitmap is refused.
3775
+ *
3776
+ * @throws {ValidationError} if `other` is not a `RoaringBitmap` of this copy of the package.
3777
+ */
3778
+ isSubset(other) {
3779
+ return this.#bitmap.isSubset(_RoaringBitmap.#operand(other));
3780
+ }
3781
+ /**
3782
+ * Whether both bitmaps hold exactly the same ids, whatever the kinds of their containers or the bytes they would
3783
+ * serialize to. Neither bitmap changes.
3784
+ *
3785
+ * @throws {ValidationError} if `other` is not a `RoaringBitmap` of this copy of the package.
3786
+ */
3787
+ isEqual(other) {
3788
+ return this.#bitmap.isEqual(_RoaringBitmap.#operand(other));
3789
+ }
3790
+ /**
3791
+ * The ids both bitmaps hold, as a new bitmap. Neither operand changes, and the result holds storage of its own.
3792
+ *
3793
+ * @throws {ValidationError} if an operand is not a `RoaringBitmap` of this copy of the package.
3794
+ */
3795
+ static and(a, b) {
3796
+ return _RoaringBitmap.#wrap(TsBitmap.and(_RoaringBitmap.#operand(a), _RoaringBitmap.#operand(b)));
3797
+ }
3798
+ /**
3799
+ * The ids either bitmap holds, as a new bitmap. Neither operand changes. A container only `a` holds is shared with
3800
+ * the result copy-on-write, so the next write to it, on either side, copies it once.
3801
+ *
3802
+ * @throws {ValidationError} if an operand is not a `RoaringBitmap` of this copy of the package.
3803
+ */
3804
+ static or(a, b) {
3805
+ return _RoaringBitmap.#wrap(TsBitmap.or(_RoaringBitmap.#operand(a), _RoaringBitmap.#operand(b)));
3806
+ }
3807
+ /**
3808
+ * The ids exactly one of the bitmaps holds, as a new bitmap. Neither operand changes (see {@link RoaringBitmap.or}
3809
+ * for what is shared).
3810
+ *
3811
+ * @throws {ValidationError} if an operand is not a `RoaringBitmap` of this copy of the package.
3812
+ */
3813
+ static xor(a, b) {
3814
+ return _RoaringBitmap.#wrap(TsBitmap.xor(_RoaringBitmap.#operand(a), _RoaringBitmap.#operand(b)));
3815
+ }
3816
+ /**
3817
+ * The ids of `a` that `b` lacks, as a new bitmap. Neither operand changes (see {@link RoaringBitmap.or} for what is
3818
+ * shared).
3819
+ *
3820
+ * @throws {ValidationError} if an operand is not a `RoaringBitmap` of this copy of the package.
3821
+ */
3822
+ static andNot(a, b) {
3823
+ return _RoaringBitmap.#wrap(
3824
+ TsBitmap.andNot(_RoaringBitmap.#operand(a), _RoaringBitmap.#operand(b))
3825
+ );
3826
+ }
3827
+ /**
3828
+ * The union of every bitmap of `bitmaps`, as a new bitmap that owns its storage (an empty list gives the empty set).
3829
+ * No operand changes, and none is flagged: the result accumulates in containers of its own.
3830
+ *
3831
+ * @throws {ValidationError} if `bitmaps` is not an iterable, or holds anything that is not a `RoaringBitmap` of this
3832
+ * copy of the package; nothing is combined then.
3833
+ */
3834
+ static orMany(bitmaps) {
3835
+ if (typeof bitmaps !== "object" || bitmaps === null || !(Symbol.iterator in bitmaps)) {
3836
+ throw new ValidationError5("orMany takes an iterable of RoaringBitmap");
3837
+ }
3838
+ const parts = Array.from(bitmaps, (b) => _RoaringBitmap.#operand(b));
3839
+ return _RoaringBitmap.#wrap(TsBitmap.orMany(parts));
3840
+ }
3841
+ /** The ids in ascending order, each once. A bitmap that changes during the walk gives unspecified ids, and no error. */
3842
+ [Symbol.iterator]() {
3843
+ return this.#bitmap[Symbol.iterator]();
3844
+ }
3845
+ /** The ids as a new ascending array. A bitmap too large to allocate as one throws the runtime's `RangeError`. */
3846
+ toArray() {
3847
+ return this.#bitmap.toArray();
3848
+ }
3849
+ /** The ids as a new ascending `Uint32Array` the caller owns, never a view of the bitmap's storage. */
3850
+ toUint32Array() {
3851
+ return this.#bitmap.toUint32Array();
3852
+ }
3853
+ /**
3854
+ * The portable Roaring bytes, in a new `Uint8Array`. Call {@link RoaringBitmap.runOptimize} first when the bitmap was
3855
+ * decoded from bytes another writer made: its run containers stay as they were, and a bitmap that serializes over
3856
+ * the size cap is refused by a load.
3857
+ *
3858
+ * @param format `'portable'`, the only format there is, or nothing.
3859
+ * @throws {ValidationError} for any other argument.
3860
+ */
3861
+ serialize(format) {
3862
+ if (format !== void 0 && format !== "portable") {
3863
+ throw new ValidationError5(
3864
+ `a bitmap serializes only as serialize() or serialize('portable'); got ${kindOf(format)}`
3865
+ );
3866
+ }
3867
+ return this.#bitmap.serialize();
3868
+ }
3869
+ /**
3870
+ * Re-encode every container in the smallest form (a run container only where it is strictly smaller than the plain
3871
+ * one), so `serialize()` afterwards depends on the set alone. Membership is unchanged.
3872
+ *
3873
+ * @returns whether the bitmap holds at least one run container afterwards, not whether anything changed.
3874
+ */
3875
+ runOptimize() {
3876
+ this.#bitmap.optimize();
3877
+ return this.#bitmap.hasRunContainer();
3878
+ }
3879
+ };
3880
+
3881
+ // src/index.ts
2223
3882
  import {
2224
3883
  excludingReservedRows as excludingReservedRows2,
2225
3884
  readRetentionPolicy,
@@ -2314,6 +3973,29 @@ var CALL_KEYS = {
2314
3973
  "allowAbsentOperands",
2315
3974
  "exclude"
2316
3975
  ]),
3976
+ intersectCount: keysOf()([
3977
+ "after",
3978
+ "through",
3979
+ "concurrency",
3980
+ "budget",
3981
+ "allowAbsentOperands",
3982
+ "exclude"
3983
+ ]),
3984
+ unionCount: keysOf()([
3985
+ "after",
3986
+ "through",
3987
+ "concurrency",
3988
+ "budget",
3989
+ "allowAbsentOperands",
3990
+ "exclude"
3991
+ ]),
3992
+ andNotCount: keysOf()([
3993
+ "after",
3994
+ "through",
3995
+ "concurrency",
3996
+ "budget",
3997
+ "allowAbsentOperands"
3998
+ ]),
2317
3999
  into: keysOf()([
2318
4000
  "after",
2319
4001
  "through",
@@ -2391,6 +4073,9 @@ var MISPLACED = {
2391
4073
  range: outside(CALL_KEYS.into, CALL_KEYS.range),
2392
4074
  andNot: outside(CALL_KEYS.into, CALL_KEYS.andNot),
2393
4075
  combine: outside(CALL_KEYS.into, CALL_KEYS.combine),
4076
+ intersectCount: outside(CALL_KEYS.into, CALL_KEYS.intersectCount),
4077
+ unionCount: outside(CALL_KEYS.into, CALL_KEYS.unionCount),
4078
+ andNotCount: outside(CALL_KEYS.into, CALL_KEYS.andNotCount),
2394
4079
  andNotInto: outside(CALL_KEYS.into, CALL_KEYS.andNotInto),
2395
4080
  exportSegments: ["codec"]
2396
4081
  };
@@ -3494,8 +5179,8 @@ var CloudRoaring = class _CloudRoaring {
3494
5179
  * with `serialize('portable')` such as `roaring`'s `RoaringBitmap32`, or `{ serialized }`, portable Roaring bytes.
3495
5180
  * A bitmap is checked (size cap, structure, safe deserializer) before the first request, written from its own
3496
5181
  * containers with no per-id work, and gives the generation chunk for chunk what its ids would. An
3497
- * iterable with a `serialize` method (a `RoaringBitmap32`, another copy's bitmap, or a bitmap `deserializePortable`
3498
- * returned) passed as ids loads as `{ bitmap }` and is not iterated. A `Uint8Array` or `Buffer` passed as ids is
5182
+ * iterable with a `serialize` method (a `RoaringBitmap32`, another copy's bitmap, or a `RoaringBitmap`
5183
+ * of this package) passed as ids loads as `{ bitmap }` and is not iterated. A `Uint8Array` or `Buffer` passed as ids is
3499
5184
  * refused with `ValidationError`, since each byte would load as an id, even when it has a `serialize` of its own:
3500
5185
  * pass bytes as `{ serialized }`.
3501
5186
  *
@@ -4101,7 +5786,7 @@ var CloudRoaring = class _CloudRoaring {
4101
5786
  /**
4102
5787
  * **Export ("eject") every registered segment's current generation** through the injected `sink`, using only
4103
5788
  * public read APIs — so your data is readable **without CloudRoaring** (the exit path; see the README's "Your
4104
- * data stays yours"). `format: 'roaring'` (default) writes one **portable RoaringBitmap32** per segment
5789
+ * data stays yours"). `format: 'roaring'` (default) writes one **portable Roaring bitmap** per segment
4105
5790
  * (loadable by any roaring library); `'ndjson'` writes newline-delimited ids (zero-dependency, streaming).
4106
5791
  * Enumerates via the store's **own** registry (needs one — throws {@link UnsupportedError} otherwise) so the
4107
5792
  * enumeration and the read path provably share one registry. Encrypted segments are decrypted transparently
@@ -4157,7 +5842,7 @@ function operandsLabel(verb) {
4157
5842
  }
4158
5843
  function refuseNoOperands(verb) {
4159
5844
  throw new ValidationError6(
4160
- verb === "intersect" ? "intersect requires at least one segment to intersect with; to read every id of one segment, use iterate()" : "intersectInto requires at least one segment to intersect with; to copy this segment into dest, call materializeMany({ operands: { src: thisSegment }, outputs: [{ dest, expr: { or: ['src'] } }], keep })"
5845
+ verb === "intersect" ? "intersect requires at least one segment to intersect with; to read every id of one segment, use iterate()" : verb === "intersectCount" ? "intersectCount requires at least one segment to intersect with; to count one segment, use count()" : "intersectInto requires at least one segment to intersect with; to copy this segment into dest, call materializeMany({ operands: { src: thisSegment }, outputs: [{ dest, expr: { or: ['src'] } }], keep })"
4161
5846
  );
4162
5847
  }
4163
5848
  var AS_IDS = {
@@ -4867,6 +6552,111 @@ var Segment = class _Segment {
4867
6552
  );
4868
6553
  return this.combineInto("andNotInto", dest, excludes, options);
4869
6554
  }
6555
+ /**
6556
+ * How many ids `this ∩ others…` holds (minus `exclude`): the length of what {@link intersect} streams, without
6557
+ * streaming it. Every key all the operands hold is decoded and counted as the stream reads it, and a key only some
6558
+ * operands hold is not read, so the call makes the requests {@link intersect} makes and returns a number instead of
6559
+ * the ids. It is exact: it never answers a key from an index, so it trusts nothing {@link count} trusts.
6560
+ *
6561
+ * The range, `concurrency`, `budget`, `allowAbsentOperands` and `exclude` are {@link intersect}'s; a write option fails
6562
+ * the call with {@link ValidationError} before any request, and so does an empty `others` (to count one segment, use
6563
+ * {@link count}).
6564
+ *
6565
+ * Like a stream, a count that runs while a segment is erased or reloaded can describe two instants, within the bound
6566
+ * the streams state. A union or a difference, and an intersection with an `exclude`, looks at its operands'
6567
+ * generations every `concurrency` keys; an intersection with no `exclude` makes no such look, since it decodes every
6568
+ * key and so shows a move in the chunks it decodes, as its stream does. Either way it plans again above the last key
6569
+ * it took when one moved. A pinned handle counts the generation it pinned, and each pinned operand's object is
6570
+ * looked up once before the first key (one footer read each, which `budget` does not charge, and which the stream
6571
+ * does not make), and again at each look where there is one, so an erasure of what it pinned fails the count with
6572
+ * {@link NotFoundError}; a
6573
+ * fault the look meets other than a transient one, which is retried, is raised as it is. A call that involves a
6574
+ * handle whose lease has ended, or has ended by the next look, throws {@link LeaseExpiredError}.
6575
+ */
6576
+ async intersectCount(others, options) {
6577
+ checkOptions(
6578
+ options,
6579
+ "intersectCount",
6580
+ CALL_KEYS.intersectCount,
6581
+ ["allowAbsentOperands"],
6582
+ MISPLACED.intersectCount
6583
+ );
6584
+ return this.countCombine("intersect", others, options ?? void 0);
6585
+ }
6586
+ /**
6587
+ * How many ids `this ∪ others…` holds (minus `exclude`): the length of what {@link union} streams, without streaming
6588
+ * it. A chunk key only one operand holds, that no `exclude` holds and the range does not cut, is answered from that
6589
+ * operand's index, so a union of segments that mostly do not overlap reads little of them; every other key is
6590
+ * decoded and counted. On handles that are not pinned it makes no more requests than {@link union} does, and reads
6591
+ * fewer bytes when the shared keys are few. An empty `others`, with no `exclude` and no range, is {@link count} of
6592
+ * `this`, answered from the registry row when it can be; when that figure is 0 it adds one registry read, to refuse
6593
+ * a segment that does not exist as the stream does.
6594
+ *
6595
+ * What it trusts: the index, for each key it answers without decoding, as {@link count} does, so a party who can write
6596
+ * an object's index can make that key's figure wrong; a decoded key is exact. A source with no per-chunk counts
6597
+ * decodes every key. It takes the options {@link intersectCount} takes; the erasure bound, the lease checks and the
6598
+ * pinned handles are as for {@link intersectCount}, a pinned operand adding a footer read before the first key and at
6599
+ * each look. An empty `others` on a pinned handle is {@link count} of the pin, with no look.
6600
+ */
6601
+ async unionCount(others, options) {
6602
+ checkOptions(
6603
+ options,
6604
+ "unionCount",
6605
+ CALL_KEYS.unionCount,
6606
+ ["allowAbsentOperands"],
6607
+ MISPLACED.unionCount
6608
+ );
6609
+ return this.countCombine("union", others, options ?? void 0);
6610
+ }
6611
+ /**
6612
+ * How many ids `this \ (excludes…)` holds: the length of what {@link andNot} streams, without streaming it. A chunk
6613
+ * key of `this` that no exclude holds and the range does not cut is answered from its index and not read; a key an
6614
+ * exclude shares is decoded and counted. On handles that are not pinned it makes no more requests than {@link andNot}
6615
+ * does, and reads fewer bytes when the excludes overlap little of `this`. An empty `excludes`, with no range, is
6616
+ * {@link count} of `this` (the stream of it is the whole of `this`), answered from the registry row when it can be,
6617
+ * with one registry read added when that figure is 0.
6618
+ *
6619
+ * It takes the options {@link andNot} takes (every one of {@link intersectCount}'s but `exclude`, which a count of a
6620
+ * difference has no use for, since `excludes` is its subtraction) and trusts what {@link unionCount} trusts. The
6621
+ * erasure bound, the lease checks and the pinned handles are as for {@link intersectCount}.
6622
+ */
6623
+ async andNotCount(excludes, options) {
6624
+ checkOptions(
6625
+ options,
6626
+ "andNotCount",
6627
+ CALL_KEYS.andNotCount,
6628
+ ["allowAbsentOperands"],
6629
+ MISPLACED.andNotCount
6630
+ );
6631
+ return this.countCombine("andNot", excludes, options ?? void 0);
6632
+ }
6633
+ /** The one body of the three count methods, after each has checked its own options. */
6634
+ async countCombine(verb, operands, options) {
6635
+ const name = `${verb}Count`;
6636
+ const exclude = verb === "andNot" ? NO_SEGMENTS : this.excludesOf(options);
6637
+ const others = segmentList(
6638
+ operands,
6639
+ verb === "andNot" ? `${name}: \`excludes\`` : `${name}: \`others\``
6640
+ );
6641
+ if (verb === "intersect" && others.length === 0) refuseNoOperands("intersectCount");
6642
+ const handles = [this, ...others, ...exclude];
6643
+ this.assertSegments(name, verb === "andNot" ? "an exclude" : "an operand", others);
6644
+ this.assertSegments(name, "an exclude", exclude);
6645
+ this.assertLeases(handles);
6646
+ const engine = this.combineEngine(handles) ?? this.engine;
6647
+ const read = options == null ? void 0 : readOptions(options);
6648
+ const guard2 = handles.some((h) => h.leaseHold !== void 0) ? () => this.assertLeases(handles) : void 0;
6649
+ const opts = guard2 === void 0 ? read : { ...read, guard: guard2 };
6650
+ const refs = others.map((o) => o.ref);
6651
+ if (verb === "andNot") return engine.combineCount([this.ref], refs, "all", verb, opts);
6652
+ return engine.combineCount(
6653
+ [this.ref, ...refs],
6654
+ exclude.map((o) => o.ref),
6655
+ verb === "union" ? "any" : "all",
6656
+ verb,
6657
+ opts
6658
+ );
6659
+ }
4870
6660
  /**
4871
6661
  * The one body of the three combines, read as ids or as chunks. `operands` is `others` for `intersect` and
4872
6662
  * `union`, and `excludes` for `andNot`, which takes no `exclude` option.
@@ -4945,13 +6735,13 @@ export {
4945
6735
  MemoryStorage,
4946
6736
  NotFoundError2 as NotFoundError,
4947
6737
  RecordingAuditSink,
6738
+ RoaringBitmap,
4948
6739
  Segment,
4949
6740
  StaleOperandError,
4950
6741
  TransientError,
4951
6742
  UnsupportedError3 as UnsupportedError,
4952
6743
  ValidationError7 as ValidationError,
4953
6744
  WriteConflictError2 as WriteConflictError,
4954
- deserializePortable,
4955
6745
  destroySegment,
4956
6746
  eraseNamespace,
4957
6747
  errorKind2 as errorKind,