@cloudbitmaps/roaring 0.23.0 → 0.24.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.
@@ -26,7 +26,7 @@ import {
26
26
  MAX_LEASE_MS,
27
27
  NotFoundError,
28
28
  UnsupportedError as UnsupportedError2,
29
- ValidationError as ValidationError5,
29
+ ValidationError as ValidationError6,
30
30
  errorKind,
31
31
  WriteConflictError,
32
32
  checkBudget,
@@ -130,8 +130,10 @@ function refuseReservedNamespace(namespace) {
130
130
  }
131
131
 
132
132
  // src/roaring-codec.ts
133
- import roaring from "roaring";
134
- import { IntegrityError as IntegrityError2, ValidationError as ValidationError2, decodeSerialized } from "@cloudbitmaps/core";
133
+ import { ValidationError as ValidationError3, decodeSerialized } from "@cloudbitmaps/core";
134
+
135
+ // src/ts-roaring/bitmap.ts
136
+ import { IntegrityError as IntegrityError3, ValidationError as ValidationError2 } from "@cloudbitmaps/core";
135
137
 
136
138
  // src/portable/layout.ts
137
139
  import { IntegrityError } from "@cloudbitmaps/core";
@@ -149,45 +151,10 @@ function overrun(bytes, offset, length, what) {
149
151
  `portable roaring: ${what} needs bytes [${offset}, ${offset + length}) of a ${bytes.byteLength}-byte buffer`
150
152
  );
151
153
  }
152
- function checkPortableLayout(bytes) {
153
- return walk(bytes, null);
154
- }
155
- var SINGLE_HEADER_BYTES = 16;
156
- var SINGLE_RUN_HEADER_BYTES = 9;
157
- function* containerPayloads(bytes) {
158
- if (bytes.byteLength === 0) return;
159
- const { view, count, runFlagsAt, descriptiveAt, bodiesAt } = header(bytes);
160
- let pos = bodiesAt;
161
- let previousKey = -1;
162
- for (let i = 0; i < count; i++) {
163
- const key = view.getUint16(descriptiveAt + i * 4, true);
164
- if (key <= previousKey) {
165
- throw new IntegrityError(
166
- `portable roaring: container keys are not strictly ascending (${previousKey} then ${key} at index ${i})`
167
- );
168
- }
169
- previousKey = key;
170
- const cardinality = view.getUint16(descriptiveAt + i * 4 + 2, true) + 1;
171
- const isRun = runFlagsAt >= 0 && (bytes[runFlagsAt + (i >>> 3)] & 1 << (i & 7)) !== 0;
172
- const kind = isRun ? RUN : cardinality > ARRAY_MAX_CARDINALITY ? BITMAP : ARRAY;
173
- const size = checkContainer(bytes, view, pos, kind, cardinality, i);
174
- const headerBytes = isRun ? SINGLE_RUN_HEADER_BYTES : SINGLE_HEADER_BYTES;
175
- const payload = new Uint8Array(headerBytes + size);
176
- const out = new DataView(payload.buffer);
177
- if (isRun) {
178
- out.setUint32(0, SERIAL_COOKIE, true);
179
- payload[4] = 1;
180
- out.setUint16(7, cardinality - 1, true);
181
- } else {
182
- out.setUint32(0, SERIAL_COOKIE_NO_RUNCONTAINER, true);
183
- out.setUint32(4, 1, true);
184
- out.setUint16(10, cardinality - 1, true);
185
- out.setUint32(12, SINGLE_HEADER_BYTES, true);
186
- }
187
- payload.set(bytes.subarray(pos, pos + size), headerBytes);
188
- pos += size;
189
- yield { chunkKey: key, payload, cardinality };
190
- }
154
+ function parsePortableLayout(bytes) {
155
+ const containers = [];
156
+ walk(bytes, containers);
157
+ return containers;
191
158
  }
192
159
  function header(bytes) {
193
160
  const length = bytes.byteLength;
@@ -338,184 +305,1579 @@ function popcount(view, at) {
338
305
  return bits;
339
306
  }
340
307
 
341
- // src/roaring-codec.ts
342
- var { RoaringBitmap32, SerializationFormat, DeserializationFormat } = roaring;
343
- var SafeBitmap = class _SafeBitmap {
344
- bitmap;
345
- constructor(bitmap) {
346
- this.bitmap = bitmap;
308
+ // src/ts-roaring/containers.ts
309
+ var ARRAY2 = 0;
310
+ var BITSET = 1;
311
+ var RUN2 = 2;
312
+ var WORDS = 2048;
313
+ var BITSET_BYTES = 8192;
314
+ var GALLOP_SKEW = 16;
315
+ var LITTLE_ENDIAN = new Uint8Array(Uint16Array.of(1).buffer)[0] === 1;
316
+ var Container = class {
317
+ constructor(kind, data, off, len, card, shared) {
318
+ this.kind = kind;
319
+ this.data = data;
320
+ this.off = off;
321
+ this.len = len;
322
+ this.card = card;
323
+ this.shared = shared;
324
+ }
325
+ kind;
326
+ data;
327
+ off;
328
+ len;
329
+ card;
330
+ shared;
331
+ };
332
+ function lows16(c) {
333
+ return c.data;
334
+ }
335
+ function words32(c) {
336
+ return c.data;
337
+ }
338
+ function arrayContainer(values, card) {
339
+ return new Container(ARRAY2, values, 0, card, card, false);
340
+ }
341
+ function bitsetContainer(words, card) {
342
+ return new Container(BITSET, words, 0, 0, card, false);
343
+ }
344
+ function runContainer(pairs, runs, card) {
345
+ return new Container(RUN2, pairs, 0, runs, card, false);
346
+ }
347
+ var valueScratch = new Uint16Array(8192);
348
+ var pairScratch = new Uint16Array(8192);
349
+ var SCRATCH_KEEP = 65536;
350
+ function values16(n) {
351
+ if (valueScratch.length >= n) return valueScratch;
352
+ if (n > SCRATCH_KEEP) return new Uint16Array(n);
353
+ valueScratch = new Uint16Array(Math.max(n, Math.min(2 * valueScratch.length, SCRATCH_KEEP)));
354
+ return valueScratch;
355
+ }
356
+ function pairs16(n) {
357
+ if (pairScratch.length >= n) return pairScratch;
358
+ if (n > SCRATCH_KEEP) return new Uint16Array(n);
359
+ pairScratch = new Uint16Array(Math.max(n, Math.min(2 * pairScratch.length, SCRATCH_KEEP)));
360
+ return pairScratch;
361
+ }
362
+ function arrayOfScratch(scratch, n) {
363
+ return n === 0 ? null : arrayContainer(scratch.slice(0, n), n);
364
+ }
365
+ function popcount32(word) {
366
+ let w = word - (word >>> 1 & 1431655765);
367
+ w = (w & 858993459) + (w >>> 2 & 858993459);
368
+ return Math.imul(w + (w >>> 4) & 252645135, 16843009) >>> 24;
369
+ }
370
+ function popcountWords(d) {
371
+ let total = 0;
372
+ let ones = 0;
373
+ let twos = 0;
374
+ let fours = 0;
375
+ let eights = 0;
376
+ for (let i = 0; i < WORDS; i += 16) {
377
+ let u;
378
+ let twosA;
379
+ let twosB;
380
+ let foursA;
381
+ let foursB;
382
+ let x = d[i];
383
+ let y = d[i + 1];
384
+ u = ones ^ x;
385
+ twosA = ones & x | u & y;
386
+ ones = u ^ y;
387
+ x = d[i + 2];
388
+ y = d[i + 3];
389
+ u = ones ^ x;
390
+ twosB = ones & x | u & y;
391
+ ones = u ^ y;
392
+ u = twos ^ twosA;
393
+ foursA = twos & twosA | u & twosB;
394
+ twos = u ^ twosB;
395
+ x = d[i + 4];
396
+ y = d[i + 5];
397
+ u = ones ^ x;
398
+ twosA = ones & x | u & y;
399
+ ones = u ^ y;
400
+ x = d[i + 6];
401
+ y = d[i + 7];
402
+ u = ones ^ x;
403
+ twosB = ones & x | u & y;
404
+ ones = u ^ y;
405
+ u = twos ^ twosA;
406
+ foursB = twos & twosA | u & twosB;
407
+ twos = u ^ twosB;
408
+ u = fours ^ foursA;
409
+ const eightsA = fours & foursA | u & foursB;
410
+ fours = u ^ foursB;
411
+ x = d[i + 8];
412
+ y = d[i + 9];
413
+ u = ones ^ x;
414
+ twosA = ones & x | u & y;
415
+ ones = u ^ y;
416
+ x = d[i + 10];
417
+ y = d[i + 11];
418
+ u = ones ^ x;
419
+ twosB = ones & x | u & y;
420
+ ones = u ^ y;
421
+ u = twos ^ twosA;
422
+ foursA = twos & twosA | u & twosB;
423
+ twos = u ^ twosB;
424
+ x = d[i + 12];
425
+ y = d[i + 13];
426
+ u = ones ^ x;
427
+ twosA = ones & x | u & y;
428
+ ones = u ^ y;
429
+ x = d[i + 14];
430
+ y = d[i + 15];
431
+ u = ones ^ x;
432
+ twosB = ones & x | u & y;
433
+ ones = u ^ y;
434
+ u = twos ^ twosA;
435
+ foursB = twos & twosA | u & twosB;
436
+ twos = u ^ twosB;
437
+ u = fours ^ foursA;
438
+ const eightsB = fours & foursA | u & foursB;
439
+ fours = u ^ foursB;
440
+ u = eights ^ eightsA;
441
+ const sixteens = eights & eightsA | u & eightsB;
442
+ eights = u ^ eightsB;
443
+ total += popcount32(sixteens);
444
+ }
445
+ return 16 * total + 8 * popcount32(eights) + 4 * popcount32(fours) + 2 * popcount32(twos) + popcount32(ones);
446
+ }
447
+ function setRange(words, start, end) {
448
+ const first = start >>> 5;
449
+ const last = end >>> 5;
450
+ const head = 4294967295 << (start & 31) >>> 0;
451
+ const tail = 4294967295 >>> 31 - (end & 31);
452
+ if (first === last) {
453
+ words[first] = words[first] | head & tail;
454
+ return;
455
+ }
456
+ words[first] = words[first] | head;
457
+ for (let i = first + 1; i < last; i++) words[i] = 4294967295;
458
+ words[last] = words[last] | tail;
459
+ }
460
+ function clearRange(words, start, end) {
461
+ const first = start >>> 5;
462
+ const last = end >>> 5;
463
+ const head = 4294967295 << (start & 31) >>> 0;
464
+ const tail = 4294967295 >>> 31 - (end & 31);
465
+ if (first === last) {
466
+ words[first] = words[first] & ~(head & tail);
467
+ return;
468
+ }
469
+ words[first] = words[first] & ~head;
470
+ for (let i = first + 1; i < last; i++) words[i] = 0;
471
+ words[last] = words[last] & ~tail;
472
+ }
473
+ function fromSortedIds(ids, from, to) {
474
+ const n = to - from;
475
+ if (n <= ARRAY_MAX_CARDINALITY) {
476
+ const lows = new Uint16Array(n);
477
+ let count = 0;
478
+ let previous = -1;
479
+ for (let i = from; i < to; i++) {
480
+ const low = ids[i] & 65535;
481
+ if (low !== previous) lows[count++] = low;
482
+ previous = low;
483
+ }
484
+ return arrayContainer(count === n ? lows : lows.slice(0, count), count);
485
+ }
486
+ const words = new Uint32Array(WORDS);
487
+ for (let i = from; i < to; i++) {
488
+ const v = ids[i] & 65535;
489
+ words[v >>> 5] = words[v >>> 5] | 1 << (v & 31);
490
+ }
491
+ return fromWordsCard(words, popcountWords(words));
492
+ }
493
+ function fromWordsCard(words, card) {
494
+ if (card === 0) return null;
495
+ if (card > ARRAY_MAX_CARDINALITY) return bitsetContainer(words, card);
496
+ const out = new Uint16Array(card);
497
+ wordsToLows(words, out);
498
+ return arrayContainer(out, card);
499
+ }
500
+ function wordsToLows(words, out) {
501
+ let k = 0;
502
+ for (let i = 0; i < WORDS; i++) {
503
+ let w = words[i];
504
+ const base = i * 32 + 31;
505
+ while (w !== 0) {
506
+ const lowest = w & -w;
507
+ out[k++] = base - Math.clz32(lowest);
508
+ w ^= lowest;
509
+ }
510
+ }
511
+ return k;
512
+ }
513
+ function writeLows(c, out) {
514
+ if (c.kind === ARRAY2) {
515
+ out.set(lows16(c).subarray(c.off, c.off + c.len));
516
+ } else if (c.kind === BITSET) {
517
+ wordsToLows(words32(c), out);
518
+ } else {
519
+ const u16 = lows16(c);
520
+ let k = 0;
521
+ for (let r = 0; r < c.len; r++) {
522
+ const start = u16[c.off + 2 * r];
523
+ const end = start + u16[c.off + 2 * r + 1];
524
+ for (let v = start; v <= end; v++) out[k++] = v;
525
+ }
526
+ }
527
+ }
528
+ function appendIds(c, out, at, base) {
529
+ if (c.kind === ARRAY2) {
530
+ const u162 = lows16(c);
531
+ const end = c.off + c.len;
532
+ if (base === 0) {
533
+ out.set(u162.subarray(c.off, end), at);
534
+ return at + c.len;
535
+ }
536
+ for (let i = c.off; i < end; i++) out[at++] = base + u162[i];
537
+ return at;
538
+ }
539
+ if (c.kind === BITSET) {
540
+ const words = words32(c);
541
+ for (let i = 0; i < WORDS; i++) {
542
+ let w = words[i];
543
+ const top = base + i * 32 + 31;
544
+ while (w !== 0) {
545
+ const lowest = w & -w;
546
+ out[at++] = top - Math.clz32(lowest);
547
+ w ^= lowest;
548
+ }
549
+ }
550
+ return at;
551
+ }
552
+ const u16 = lows16(c);
553
+ for (let r = 0; r < c.len; r++) {
554
+ const start = u16[c.off + 2 * r];
555
+ const last = start + u16[c.off + 2 * r + 1];
556
+ if (last - start < LONG_RUN) {
557
+ for (let v = base + start; v <= base + last; v++) out[at++] = v;
558
+ continue;
559
+ }
560
+ const from = at;
561
+ out.set(iota().subarray(start, last + 1), at);
562
+ at += last - start + 1;
563
+ if (base !== 0) for (let i = from; i < at; i++) out[i] = out[i] + base;
564
+ }
565
+ return at;
566
+ }
567
+ var LONG_RUN = 48;
568
+ var iotaTable;
569
+ function iota() {
570
+ if (iotaTable === void 0) {
571
+ iotaTable = new Uint16Array(65536);
572
+ for (let i = 0; i < 65536; i++) iotaTable[i] = i;
573
+ }
574
+ return iotaTable;
575
+ }
576
+ function toWords(c) {
577
+ if (c.kind === BITSET) return words32(c);
578
+ const words = new Uint32Array(WORDS);
579
+ const u16 = lows16(c);
580
+ if (c.kind === ARRAY2) {
581
+ for (let i = c.off; i < c.off + c.len; i++) {
582
+ const v = u16[i];
583
+ words[v >>> 5] = words[v >>> 5] | 1 << (v & 31);
584
+ }
585
+ } else {
586
+ for (let r = 0; r < c.len; r++) {
587
+ const start = u16[c.off + 2 * r];
588
+ setRange(words, start, start + u16[c.off + 2 * r + 1]);
589
+ }
590
+ }
591
+ return words;
592
+ }
593
+ function demote(c) {
594
+ if (c.kind !== RUN2) return c;
595
+ if (c.card > ARRAY_MAX_CARDINALITY) return bitsetContainer(toWords(c), c.card);
596
+ const out = new Uint16Array(c.card);
597
+ writeLows(c, out);
598
+ return arrayContainer(out, c.card);
599
+ }
600
+ function cloneContainer(c) {
601
+ if (c.kind === BITSET) return bitsetContainer(words32(c).slice(), c.card);
602
+ const copy = lows16(c).slice(c.off, c.off + (c.kind === ARRAY2 ? c.len : 2 * c.len));
603
+ return new Container(c.kind, copy, 0, c.len, c.card, false);
604
+ }
605
+ function writableWords(c) {
606
+ return c.shared ? words32(c).slice() : words32(c);
607
+ }
608
+ function lowerBound(data, off, len, low, stride) {
609
+ let lo = 0;
610
+ let hi = len;
611
+ while (lo < hi) {
612
+ const mid = lo + hi >>> 1;
613
+ if (data[off + mid * stride] < low) lo = mid + 1;
614
+ else hi = mid;
615
+ }
616
+ return lo;
617
+ }
618
+ function gallop(data, off, from, end, target) {
619
+ let step = 1;
620
+ let lo = from;
621
+ let hi = from;
622
+ while (hi < end && data[off + hi] < target) {
623
+ lo = hi + 1;
624
+ hi += step;
625
+ step *= 2;
626
+ }
627
+ if (hi > end) hi = end;
628
+ while (lo < hi) {
629
+ const mid = lo + hi >>> 1;
630
+ if (data[off + mid] < target) lo = mid + 1;
631
+ else hi = mid;
632
+ }
633
+ return lo;
634
+ }
635
+ function containerHas(c, low) {
636
+ if (c.kind === BITSET)
637
+ return (c.data[low >>> 5] >>> (low & 31) & 1) === 1;
638
+ const u16 = c.data;
639
+ if (c.kind === ARRAY2) {
640
+ const at = lowerBound(u16, c.off, c.len, low, 1);
641
+ return at < c.len && u16[c.off + at] === low;
642
+ }
643
+ const after = lowerBound(u16, c.off, c.len, low + 1, 2);
644
+ if (after === 0) return false;
645
+ const r = c.off + 2 * (after - 1);
646
+ return low <= u16[r] + u16[r + 1];
647
+ }
648
+ function containerAdd(c, low) {
649
+ if (containerHas(c, low)) return c;
650
+ const plain = demote(c);
651
+ if (plain.kind === BITSET) {
652
+ const words = writableWords(plain);
653
+ words[low >>> 5] = words[low >>> 5] | 1 << (low & 31);
654
+ return bitsetContainer(words, plain.card + 1);
655
+ }
656
+ if (plain.card === ARRAY_MAX_CARDINALITY) {
657
+ const words = toWords(plain);
658
+ words[low >>> 5] = words[low >>> 5] | 1 << (low & 31);
659
+ return bitsetContainer(words, plain.card + 1);
660
+ }
661
+ const old = lows16(plain);
662
+ const at = lowerBound(old, plain.off, plain.len, low, 1);
663
+ let u16 = old;
664
+ if (!plain.shared && plain.off === 0 && old.length > plain.len) {
665
+ u16.copyWithin(at + 1, at, plain.len);
666
+ } else {
667
+ u16 = new Uint16Array(Math.min(ARRAY_MAX_CARDINALITY, Math.max(8, plain.len * 2)));
668
+ u16.set(old.subarray(plain.off, plain.off + at));
669
+ u16.set(old.subarray(plain.off + at, plain.off + plain.len), at + 1);
670
+ }
671
+ u16[at] = low;
672
+ return arrayContainer(u16, plain.card + 1);
673
+ }
674
+ function containerRemove(c, low) {
675
+ if (!containerHas(c, low)) return c;
676
+ if (c.card === 1) return null;
677
+ const plain = demote(c);
678
+ if (plain.kind === BITSET) {
679
+ const words = writableWords(plain);
680
+ words[low >>> 5] = words[low >>> 5] & ~(1 << (low & 31));
681
+ return fromWordsCard(words, plain.card - 1);
682
+ }
683
+ const old = lows16(plain);
684
+ const at = lowerBound(old, plain.off, plain.len, low, 1);
685
+ if (!plain.shared && plain.off === 0) {
686
+ old.copyWithin(at, at + 1, plain.len);
687
+ return arrayContainer(old, plain.card - 1);
688
+ }
689
+ const u16 = new Uint16Array(plain.len - 1);
690
+ u16.set(old.subarray(plain.off, plain.off + at));
691
+ u16.set(old.subarray(plain.off + at + 1, plain.off + plain.len), at);
692
+ return arrayContainer(u16, plain.card - 1);
693
+ }
694
+ function containerMax(c) {
695
+ if (c.kind === ARRAY2) return c.data[c.off + c.len - 1];
696
+ if (c.kind === RUN2) {
697
+ const u16 = c.data;
698
+ return u16[c.off + 2 * c.len - 2] + u16[c.off + 2 * c.len - 1];
699
+ }
700
+ const words = words32(c);
701
+ for (let i = WORDS - 1; i >= 0; i--) {
702
+ const w = words[i];
703
+ if (w !== 0) return i * 32 + 31 - Math.clz32(w);
704
+ }
705
+ throw new RangeError("a bitset container holds no bits");
706
+ }
707
+ function runCount(c, stop) {
708
+ if (c.kind === RUN2) return c.len;
709
+ let runs = 0;
710
+ if (c.kind === ARRAY2) {
711
+ const u16 = lows16(c);
712
+ let previous = -2;
713
+ for (let i = c.off; i < c.off + c.len; i++) {
714
+ const v = u16[i];
715
+ if (v !== previous + 1 && ++runs >= stop) return runs;
716
+ previous = v;
717
+ }
718
+ return runs;
719
+ }
720
+ const words = words32(c);
721
+ let carry = 0;
722
+ for (let i = 0; i < WORDS; i++) {
723
+ const w = words[i];
724
+ const starts = w & ~(w << 1 | carry);
725
+ if (starts !== 0) {
726
+ runs += popcount32(starts >>> 0);
727
+ if (runs >= stop) return runs;
728
+ }
729
+ carry = w >>> 31;
730
+ }
731
+ return runs;
732
+ }
733
+ function toRun(c, runs) {
734
+ const pairs = new Uint16Array(2 * runs);
735
+ let r = 0;
736
+ if (c.kind === ARRAY2) {
737
+ const u16 = lows16(c);
738
+ const end = c.off + c.len;
739
+ let i = c.off;
740
+ while (i < end) {
741
+ let j = i;
742
+ while (j + 1 < end && u16[j + 1] === u16[j] + 1) j++;
743
+ pairs[2 * r] = u16[i];
744
+ pairs[2 * r + 1] = j - i;
745
+ r++;
746
+ i = j + 1;
747
+ }
748
+ return runContainer(pairs, runs, c.card);
749
+ }
750
+ const words = words32(c);
751
+ let start = 0;
752
+ let carry = 0;
753
+ for (let i = 0; i < WORDS; i++) {
754
+ const w = words[i];
755
+ const next = i + 1 < WORDS ? words[i + 1] : 0;
756
+ let starts = (w & ~(w << 1 | carry)) >>> 0;
757
+ let ends = (w & ~(w >>> 1 | next << 31)) >>> 0;
758
+ carry = w >>> 31;
759
+ let both = starts | ends;
760
+ while (both !== 0) {
761
+ const bit = both & -both;
762
+ both ^= bit;
763
+ const at = i * 32 + 31 - Math.clz32(bit);
764
+ if ((starts & bit) !== 0) {
765
+ starts ^= bit;
766
+ start = at;
767
+ }
768
+ if ((ends & bit) !== 0) {
769
+ ends ^= bit;
770
+ pairs[2 * r] = start;
771
+ pairs[2 * r + 1] = at - start;
772
+ r++;
773
+ }
774
+ }
775
+ }
776
+ return runContainer(pairs, runs, c.card);
777
+ }
778
+ function optimize(c) {
779
+ const plain = c.card <= ARRAY_MAX_CARDINALITY ? 2 * c.card : BITSET_BYTES;
780
+ const runs = runCount(c, (plain - 2) / 4);
781
+ if (2 + 4 * runs < plain) return c.kind === RUN2 ? c : toRun(c, runs);
782
+ return demote(c);
783
+ }
784
+ function skewed(shorter, longer) {
785
+ return longer >= GALLOP_SKEW * shorter;
786
+ }
787
+ var PROBE_MIN = 32;
788
+ var probeWords = new Uint32Array(WORDS);
789
+ function andArrays(a, b) {
790
+ const small = a.len <= b.len ? a : b;
791
+ const big = small === a ? b : a;
792
+ const s = lows16(small);
793
+ const l = lows16(big);
794
+ const out = values16(small.len);
795
+ let n = 0;
796
+ if (small.len >= PROBE_MIN && !skewed(small.len, big.len)) {
797
+ const se = small.off + small.len;
798
+ const first = s[small.off];
799
+ const last = s[se - 1];
800
+ const le = big.off + big.len;
801
+ if (last < l[big.off] || first > l[le - 1]) return null;
802
+ const from = gallop(l, 0, big.off, le, first);
803
+ const to = gallop(l, 0, from, le, last + 1);
804
+ const words = probeWords;
805
+ for (let i2 = small.off; i2 < se; i2++) {
806
+ const v = s[i2];
807
+ words[v >>> 5] = words[v >>> 5] | 1 << (v & 31);
808
+ }
809
+ for (let j2 = from; j2 < to; j2++) {
810
+ const v = l[j2];
811
+ out[n] = v;
812
+ n += words[v >>> 5] >>> (v & 31) & 1;
813
+ }
814
+ for (let i2 = small.off; i2 < se; i2++) words[s[i2] >>> 5] = 0;
815
+ return arrayOfScratch(out, n);
816
+ }
817
+ if (skewed(small.len, big.len)) {
818
+ let at = 0;
819
+ const end = big.off + big.len;
820
+ for (let i2 = small.off; i2 < small.off + small.len; i2++) {
821
+ const v = s[i2];
822
+ at = gallop(l, 0, Math.max(at, big.off), end, v);
823
+ if (at === end) break;
824
+ if (l[at] === v) out[n++] = v;
825
+ }
826
+ return arrayOfScratch(out, n);
827
+ }
828
+ let i = small.off;
829
+ let j = big.off;
830
+ const ie = small.off + small.len;
831
+ const je = big.off + big.len;
832
+ while (i < ie && j < je) {
833
+ const x = s[i];
834
+ const y = l[j];
835
+ out[n] = x;
836
+ n += x === y ? 1 : 0;
837
+ i += x <= y ? 1 : 0;
838
+ j += x >= y ? 1 : 0;
839
+ }
840
+ return arrayOfScratch(out, n);
841
+ }
842
+ function filterByBits(a, b, keep) {
843
+ const u16 = lows16(a);
844
+ const words = words32(b);
845
+ const out = values16(a.len);
846
+ const flip = keep ? 0 : 1;
847
+ let n = 0;
848
+ for (let i = a.off; i < a.off + a.len; i++) {
849
+ const v = u16[i];
850
+ out[n] = v;
851
+ n += words[v >>> 5] >>> (v & 31) & 1 ^ flip;
852
+ }
853
+ return arrayOfScratch(out, n);
854
+ }
855
+ function filterByRuns(a, b, keep) {
856
+ const u16 = lows16(a);
857
+ const pairs = lows16(b);
858
+ const out = values16(a.len);
859
+ let n = 0;
860
+ if (keep && a.len >= b.len) {
861
+ const ae = a.off + a.len;
862
+ let i = a.off;
863
+ for (let r2 = 0; r2 < b.len && i < ae; r2++) {
864
+ const start = pairs[b.off + 2 * r2];
865
+ const end = start + pairs[b.off + 2 * r2 + 1];
866
+ while (i < ae && u16[i] < start) i++;
867
+ while (i < ae && u16[i] <= end) out[n++] = u16[i++];
868
+ }
869
+ return arrayOfScratch(out, n);
870
+ }
871
+ let r = 0;
872
+ for (let i = a.off; i < a.off + a.len; i++) {
873
+ const v = u16[i];
874
+ while (r < b.len && pairs[b.off + 2 * r] + pairs[b.off + 2 * r + 1] < v) {
875
+ r++;
876
+ }
877
+ const inside = r < b.len && pairs[b.off + 2 * r] <= v;
878
+ if (inside === keep) out[n++] = v;
879
+ }
880
+ return arrayOfScratch(out, n);
881
+ }
882
+ function andNotArrays(a, b) {
883
+ const x = lows16(a);
884
+ const y = lows16(b);
885
+ const out = values16(a.len);
886
+ let n = 0;
887
+ const je = b.off + b.len;
888
+ if (skewed(a.len, b.len)) {
889
+ let at = b.off;
890
+ for (let i2 = a.off; i2 < a.off + a.len; i2++) {
891
+ const v = x[i2];
892
+ at = gallop(y, 0, at, je, v);
893
+ if (at === je || y[at] !== v) out[n++] = v;
894
+ }
895
+ return arrayOfScratch(out, n);
896
+ }
897
+ if (b.len >= PROBE_MIN) {
898
+ const ae = a.off + a.len;
899
+ const first = x[a.off];
900
+ const last = x[ae - 1];
901
+ const from = gallop(y, 0, b.off, je, first);
902
+ const to = gallop(y, 0, from, je, last + 1);
903
+ const words = probeWords;
904
+ for (let j2 = from; j2 < to; j2++) {
905
+ const v = y[j2];
906
+ words[v >>> 5] = words[v >>> 5] | 1 << (v & 31);
907
+ }
908
+ for (let i2 = a.off; i2 < ae; i2++) {
909
+ const v = x[i2];
910
+ out[n] = v;
911
+ n += words[v >>> 5] >>> (v & 31) & 1 ^ 1;
912
+ }
913
+ for (let j2 = from; j2 < to; j2++) words[y[j2] >>> 5] = 0;
914
+ return arrayOfScratch(out, n);
915
+ }
916
+ let i = a.off;
917
+ let j = b.off;
918
+ const ie = a.off + a.len;
919
+ while (i < ie && j < je) {
920
+ const p = x[i];
921
+ const q = y[j];
922
+ out[n] = p;
923
+ n += p < q ? 1 : 0;
924
+ i += p <= q ? 1 : 0;
925
+ j += p >= q ? 1 : 0;
926
+ }
927
+ while (i < ie) out[n++] = x[i++];
928
+ return arrayOfScratch(out, n);
929
+ }
930
+ function orArrays(a, b) {
931
+ const x = lows16(a);
932
+ const y = lows16(b);
933
+ const ie = a.off + a.len;
934
+ const je = b.off + b.len;
935
+ if (a.len + b.len > ARRAY_MAX_CARDINALITY) {
936
+ const words = new Uint32Array(WORDS);
937
+ for (let i2 = a.off; i2 < ie; i2++) {
938
+ const v = x[i2];
939
+ words[v >>> 5] = words[v >>> 5] | 1 << (v & 31);
940
+ }
941
+ for (let j2 = b.off; j2 < je; j2++) {
942
+ const v = y[j2];
943
+ words[v >>> 5] = words[v >>> 5] | 1 << (v & 31);
944
+ }
945
+ return fromWordsCard(words, popcountWords(words));
946
+ }
947
+ const out = values16(a.len + b.len);
948
+ let n = 0;
949
+ let i = a.off;
950
+ let j = b.off;
951
+ while (i < ie && j < je) {
952
+ const p = x[i];
953
+ const q = y[j];
954
+ out[n++] = p < q ? p : q;
955
+ i += p <= q ? 1 : 0;
956
+ j += p >= q ? 1 : 0;
957
+ }
958
+ while (i < ie) out[n++] = x[i++];
959
+ while (j < je) out[n++] = y[j++];
960
+ return arrayOfScratch(out, n);
961
+ }
962
+ function orIntoBitset(dest, other, inPlace) {
963
+ const words = inPlace ? words32(dest) : words32(dest).slice();
964
+ if (other.kind === ARRAY2) {
965
+ const u16 = lows16(other);
966
+ let card = dest.card;
967
+ for (let i = other.off; i < other.off + other.len; i++) {
968
+ const v = u16[i];
969
+ const w = words[v >>> 5];
970
+ const bit = 1 << (v & 31);
971
+ if ((w & bit) === 0) {
972
+ words[v >>> 5] = w | bit;
973
+ card++;
974
+ }
975
+ }
976
+ return bitsetContainer(words, card);
977
+ }
978
+ if (other.kind === BITSET) {
979
+ const o = words32(other);
980
+ for (let i = 0; i < WORDS; i++) words[i] = words[i] | o[i];
981
+ } else {
982
+ const pairs = lows16(other);
983
+ for (let r = 0; r < other.len; r++) {
984
+ const start = pairs[other.off + 2 * r];
985
+ setRange(words, start, start + pairs[other.off + 2 * r + 1]);
986
+ }
987
+ }
988
+ return bitsetContainer(words, popcountWords(words));
989
+ }
990
+ function fromRunPairs(pairs, runs, card) {
991
+ if (card === 0) return null;
992
+ if (card <= ARRAY_MAX_CARDINALITY) {
993
+ const out = new Uint16Array(card);
994
+ let k = 0;
995
+ for (let r = 0; r < runs; r++) {
996
+ const start = pairs[2 * r];
997
+ const end = start + pairs[2 * r + 1];
998
+ for (let v = start; v <= end; v++) out[k++] = v;
999
+ }
1000
+ return arrayContainer(out, card);
1001
+ }
1002
+ const words = new Uint32Array(WORDS);
1003
+ for (let r = 0; r < runs; r++) {
1004
+ const start = pairs[2 * r];
1005
+ setRange(words, start, start + pairs[2 * r + 1]);
1006
+ }
1007
+ return bitsetContainer(words, card);
1008
+ }
1009
+ function andRuns(a, b) {
1010
+ const x = lows16(a);
1011
+ const y = lows16(b);
1012
+ const out = pairs16(2 * (a.len + b.len));
1013
+ let runs = 0;
1014
+ let card = 0;
1015
+ let i = 0;
1016
+ let j = 0;
1017
+ while (i < a.len && j < b.len) {
1018
+ const as = x[a.off + 2 * i];
1019
+ const ae = as + x[a.off + 2 * i + 1];
1020
+ const bs = y[b.off + 2 * j];
1021
+ const be = bs + y[b.off + 2 * j + 1];
1022
+ const lo = as > bs ? as : bs;
1023
+ const hi = ae < be ? ae : be;
1024
+ if (lo <= hi) {
1025
+ out[2 * runs] = lo;
1026
+ out[2 * runs + 1] = hi - lo;
1027
+ runs++;
1028
+ card += hi - lo + 1;
1029
+ }
1030
+ if (ae < be) i++;
1031
+ else j++;
1032
+ }
1033
+ return fromRunPairs(out, runs, card);
1034
+ }
1035
+ function orRuns(a, b) {
1036
+ const x = lows16(a);
1037
+ const y = lows16(b);
1038
+ const out = pairs16(2 * (a.len + b.len));
1039
+ let runs = 0;
1040
+ let card = 0;
1041
+ let i = 0;
1042
+ let j = 0;
1043
+ let start = -1;
1044
+ let end = -1;
1045
+ const flush = () => {
1046
+ if (start < 0) return;
1047
+ out[2 * runs] = start;
1048
+ out[2 * runs + 1] = end - start;
1049
+ runs++;
1050
+ card += end - start + 1;
1051
+ };
1052
+ while (i < a.len || j < b.len) {
1053
+ let s;
1054
+ let e;
1055
+ if (j >= b.len || i < a.len && x[a.off + 2 * i] <= y[b.off + 2 * j]) {
1056
+ s = x[a.off + 2 * i];
1057
+ e = s + x[a.off + 2 * i + 1];
1058
+ i++;
1059
+ } else {
1060
+ s = y[b.off + 2 * j];
1061
+ e = s + y[b.off + 2 * j + 1];
1062
+ j++;
1063
+ }
1064
+ if (start >= 0 && s <= end + 1) {
1065
+ if (e > end) end = e;
1066
+ } else {
1067
+ flush();
1068
+ start = s;
1069
+ end = e;
1070
+ }
1071
+ }
1072
+ flush();
1073
+ return fromRunPairs(out, runs, card);
1074
+ }
1075
+ function andNotRuns(a, b) {
1076
+ const x = lows16(a);
1077
+ const y = lows16(b);
1078
+ const out = pairs16(2 * (a.len + b.len + 1));
1079
+ let runs = 0;
1080
+ let card = 0;
1081
+ let j = 0;
1082
+ for (let i = 0; i < a.len; i++) {
1083
+ let s = x[a.off + 2 * i];
1084
+ const e = s + x[a.off + 2 * i + 1];
1085
+ while (j < b.len && y[b.off + 2 * j] + y[b.off + 2 * j + 1] < s) j++;
1086
+ let k = j;
1087
+ while (s <= e) {
1088
+ if (k >= b.len || y[b.off + 2 * k] > e) {
1089
+ out[2 * runs] = s;
1090
+ out[2 * runs + 1] = e - s;
1091
+ runs++;
1092
+ card += e - s + 1;
1093
+ break;
1094
+ }
1095
+ const bs = y[b.off + 2 * k];
1096
+ const be = bs + y[b.off + 2 * k + 1];
1097
+ if (bs > s) {
1098
+ out[2 * runs] = s;
1099
+ out[2 * runs + 1] = bs - 1 - s;
1100
+ runs++;
1101
+ card += bs - s;
1102
+ }
1103
+ s = be + 1;
1104
+ k++;
1105
+ }
1106
+ }
1107
+ return fromRunPairs(out, runs, card);
1108
+ }
1109
+ function bitsetInRuns(a, b) {
1110
+ const words = words32(a);
1111
+ const pairs = lows16(b);
1112
+ if (b.card <= ARRAY_MAX_CARDINALITY) {
1113
+ const out2 = values16(b.card);
1114
+ let n = 0;
1115
+ for (let r = 0; r < b.len; r++) {
1116
+ const start = pairs[b.off + 2 * r];
1117
+ const end = start + pairs[b.off + 2 * r + 1];
1118
+ const first = start >>> 5;
1119
+ const last = end >>> 5;
1120
+ const head = 4294967295 << (start & 31) >>> 0;
1121
+ const tail = 4294967295 >>> 31 - (end & 31);
1122
+ for (let i = first; i <= last; i++) {
1123
+ let w = words[i];
1124
+ if (i === first) w &= head;
1125
+ if (i === last) w &= tail;
1126
+ const top = i * 32 + 31;
1127
+ while (w !== 0) {
1128
+ const lowest = w & -w;
1129
+ out2[n++] = top - Math.clz32(lowest);
1130
+ w ^= lowest;
1131
+ }
1132
+ }
1133
+ }
1134
+ return arrayOfScratch(out2, n);
1135
+ }
1136
+ const out = new Uint32Array(WORDS);
1137
+ for (let r = 0; r < b.len; r++) {
1138
+ const start = pairs[b.off + 2 * r];
1139
+ const end = start + pairs[b.off + 2 * r + 1];
1140
+ const first = start >>> 5;
1141
+ const last = end >>> 5;
1142
+ const head = 4294967295 << (start & 31) >>> 0;
1143
+ const tail = 4294967295 >>> 31 - (end & 31);
1144
+ if (first === last) {
1145
+ out[first] = out[first] | words[first] & head & tail;
1146
+ } else {
1147
+ out[first] = out[first] | words[first] & head;
1148
+ for (let i = first + 1; i < last; i++) out[i] = words[i];
1149
+ out[last] = out[last] | words[last] & tail;
1150
+ }
1151
+ }
1152
+ return fromWordsCard(out, popcountWords(out));
1153
+ }
1154
+ function containerAnd(a, b, inPlace = false) {
1155
+ if (a.kind === BITSET && b.kind === BITSET) {
1156
+ const x = words32(a);
1157
+ const y = words32(b);
1158
+ const out = inPlace ? x : new Uint32Array(WORDS);
1159
+ for (let i = 0; i < WORDS; i++) out[i] = x[i] & y[i];
1160
+ return fromWordsCard(out, popcountWords(out));
1161
+ }
1162
+ if (a.kind > b.kind) return containerAnd(b, a);
1163
+ if (a.kind === ARRAY2) {
1164
+ if (b.kind === ARRAY2) return andArrays(a, b);
1165
+ return b.kind === BITSET ? filterByBits(a, b, true) : filterByRuns(a, b, true);
1166
+ }
1167
+ return b.kind === RUN2 && a.kind === RUN2 ? andRuns(a, b) : bitsetInRuns(a, b);
1168
+ }
1169
+ function containerOr(a, b, inPlace = false) {
1170
+ if (a.kind === BITSET) return orIntoBitset(a, b, inPlace);
1171
+ if (b.kind === BITSET) return orIntoBitset(b, a, false);
1172
+ if (a.kind === ARRAY2 && b.kind === ARRAY2) return orArrays(a, b);
1173
+ if (a.kind === RUN2 && b.kind === RUN2) return orRuns(a, b);
1174
+ const words = toWords(a.kind === RUN2 ? a : b);
1175
+ return orIntoBitsetWords(words, a.kind === RUN2 ? b : a);
1176
+ }
1177
+ function orIntoBitsetWords(words, array) {
1178
+ const u16 = lows16(array);
1179
+ for (let i = array.off; i < array.off + array.len; i++) {
1180
+ const v = u16[i];
1181
+ words[v >>> 5] = words[v >>> 5] | 1 << (v & 31);
1182
+ }
1183
+ return fromWordsCard(words, popcountWords(words));
1184
+ }
1185
+ function containerAndNot(a, b, inPlace = false) {
1186
+ if (a.kind === ARRAY2) {
1187
+ if (b.kind === ARRAY2) return andNotArrays(a, b);
1188
+ return b.kind === BITSET ? filterByBits(a, b, false) : filterByRuns(a, b, false);
1189
+ }
1190
+ if (a.kind === RUN2 && b.kind === RUN2) return andNotRuns(a, b);
1191
+ const words = a.kind === BITSET ? inPlace ? words32(a) : words32(a).slice() : toWords(a);
1192
+ if (b.kind === ARRAY2) {
1193
+ const u16 = lows16(b);
1194
+ for (let i = b.off; i < b.off + b.len; i++) {
1195
+ const v = u16[i];
1196
+ words[v >>> 5] = words[v >>> 5] & ~(1 << (v & 31));
1197
+ }
1198
+ } else if (b.kind === BITSET) {
1199
+ const y = words32(b);
1200
+ for (let i = 0; i < WORDS; i++) words[i] = words[i] & ~y[i];
1201
+ } else {
1202
+ const pairs = lows16(b);
1203
+ for (let r = 0; r < b.len; r++) {
1204
+ const start = pairs[b.off + 2 * r];
1205
+ clearRange(words, start, start + pairs[b.off + 2 * r + 1]);
1206
+ }
1207
+ }
1208
+ return fromWordsCard(words, popcountWords(words));
1209
+ }
1210
+
1211
+ // src/ts-roaring/iterator.ts
1212
+ var DONE = { done: true, value: void 0 };
1213
+ var BitmapIterator = class {
1214
+ #keys;
1215
+ #conts;
1216
+ /** The container being walked, as an index into `#conts`, and its kind, storage and offset. */
1217
+ #at = -1;
1218
+ #kind = ARRAY2;
1219
+ #u16 = new Uint16Array(0);
1220
+ #words = new Uint32Array(0);
1221
+ #off = 0;
1222
+ /** Added to every remainder: the container's key times 65,536. */
1223
+ #base = 0;
1224
+ /** 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. */
1225
+ #pos = 0;
1226
+ #end = 0;
1227
+ /** A run container: the next value and the last of the current run. A bitset: what is left of the current word. */
1228
+ #next = 0;
1229
+ #last = -1;
1230
+ constructor(keys, conts) {
1231
+ this.#keys = keys;
1232
+ this.#conts = conts;
1233
+ }
1234
+ [Symbol.iterator]() {
1235
+ return this;
1236
+ }
1237
+ next() {
1238
+ for (; ; ) {
1239
+ if (this.#kind === ARRAY2) {
1240
+ if (this.#pos < this.#end) {
1241
+ return { done: false, value: this.#base + this.#u16[this.#pos++] };
1242
+ }
1243
+ } else if (this.#kind === BITSET) {
1244
+ let w = this.#next;
1245
+ while (w === 0 && ++this.#pos < WORDS) w = this.#words[this.#pos];
1246
+ if (w !== 0) {
1247
+ const lowest = w & -w;
1248
+ this.#next = w ^ lowest;
1249
+ return {
1250
+ done: false,
1251
+ value: this.#base + this.#pos * 32 + 31 - Math.clz32(lowest)
1252
+ };
1253
+ }
1254
+ } else {
1255
+ if (this.#next <= this.#last) return { done: false, value: this.#base + this.#next++ };
1256
+ if (this.#pos < this.#end) {
1257
+ const r = this.#off + 2 * this.#pos++;
1258
+ this.#next = this.#u16[r];
1259
+ this.#last = this.#next + this.#u16[r + 1];
1260
+ continue;
1261
+ }
1262
+ }
1263
+ if (!this.#advance()) return DONE;
1264
+ }
1265
+ }
1266
+ /** Move to the next container; `false` when there is none. */
1267
+ #advance() {
1268
+ if (++this.#at >= this.#conts.length) {
1269
+ this.#at = this.#conts.length;
1270
+ this.#kind = ARRAY2;
1271
+ this.#pos = 0;
1272
+ this.#end = 0;
1273
+ return false;
1274
+ }
1275
+ const c = this.#conts[this.#at];
1276
+ this.#kind = c.kind;
1277
+ this.#base = this.#keys[this.#at] * 65536;
1278
+ this.#off = c.off;
1279
+ if (c.kind === ARRAY2) {
1280
+ this.#u16 = c.data;
1281
+ this.#pos = c.off;
1282
+ this.#end = c.off + c.len;
1283
+ } else if (c.kind === BITSET) {
1284
+ this.#words = c.data;
1285
+ this.#pos = 0;
1286
+ this.#next = this.#words[0];
1287
+ } else {
1288
+ this.#u16 = c.data;
1289
+ this.#pos = 0;
1290
+ this.#end = c.len;
1291
+ this.#next = 0;
1292
+ this.#last = -1;
1293
+ }
1294
+ return true;
1295
+ }
1296
+ };
1297
+
1298
+ // src/ts-roaring/wire.ts
1299
+ import { IntegrityError as IntegrityError2 } from "@cloudbitmaps/core";
1300
+ function bodySize(c) {
1301
+ if (c.kind === ARRAY2) return 2 * c.len;
1302
+ if (c.kind === BITSET) return BITSET_BYTES;
1303
+ return 2 + 4 * c.len;
1304
+ }
1305
+ function putU16s(out, at, src, from, count) {
1306
+ if (LITTLE_ENDIAN) {
1307
+ out.set(new Uint8Array(src.buffer, src.byteOffset + 2 * from, 2 * count), at);
1308
+ return;
1309
+ }
1310
+ const view = new DataView(out.buffer, out.byteOffset, out.byteLength);
1311
+ for (let i = 0; i < count; i++) view.setUint16(at + 2 * i, src[from + i], true);
1312
+ }
1313
+ function writeBody(c, out, view, at) {
1314
+ if (c.kind === ARRAY2) {
1315
+ putU16s(out, at, c.data, c.off, c.len);
1316
+ } else if (c.kind === BITSET) {
1317
+ const words = c.data;
1318
+ if (LITTLE_ENDIAN) out.set(new Uint8Array(words.buffer, words.byteOffset, BITSET_BYTES), at);
1319
+ else for (let i = 0; i < WORDS; i++) view.setUint32(at + 4 * i, words[i], true);
1320
+ } else {
1321
+ view.setUint16(at, c.len, true);
1322
+ putU16s(out, at + 2, c.data, c.off, 2 * c.len);
1323
+ }
1324
+ }
1325
+ function serializeContainers(keys, conts) {
1326
+ const n = conts.length;
1327
+ let hasRun = false;
1328
+ for (let i = 0; i < n; i++) if (conts[i].kind === RUN2) hasRun = true;
1329
+ const offsets = !hasRun || n >= NO_OFFSET_THRESHOLD;
1330
+ let at = hasRun ? 4 + (n + 7 >>> 3) : 8;
1331
+ const describeAt = at;
1332
+ at += 4 * n;
1333
+ const offsetsAt = at;
1334
+ if (offsets) at += 4 * n;
1335
+ let total = at;
1336
+ for (let i = 0; i < n; i++) total += bodySize(conts[i]);
1337
+ const out = new Uint8Array(total);
1338
+ const view = new DataView(out.buffer);
1339
+ if (hasRun) {
1340
+ view.setUint32(0, SERIAL_COOKIE | n - 1 << 16, true);
1341
+ for (let i = 0; i < n; i++) {
1342
+ if (conts[i].kind === RUN2) {
1343
+ out[4 + (i >>> 3)] = out[4 + (i >>> 3)] | 1 << (i & 7);
1344
+ }
1345
+ }
1346
+ } else {
1347
+ view.setUint32(0, SERIAL_COOKIE_NO_RUNCONTAINER, true);
1348
+ view.setUint32(4, n, true);
1349
+ }
1350
+ for (let i = 0; i < n; i++) {
1351
+ const c = conts[i];
1352
+ view.setUint16(describeAt + 4 * i, keys[i], true);
1353
+ view.setUint16(describeAt + 4 * i + 2, c.card - 1, true);
1354
+ if (offsets) view.setUint32(offsetsAt + 4 * i, at, true);
1355
+ writeBody(c, out, view, at);
1356
+ at += bodySize(c);
1357
+ }
1358
+ return out;
1359
+ }
1360
+ function decodeContainers(input) {
1361
+ const bytes = Uint8Array.prototype.slice.call(input);
1362
+ const layout = parsePortableLayout(bytes);
1363
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
1364
+ const keys = new Array(layout.length);
1365
+ const conts = new Array(layout.length);
1366
+ let n = 0;
1367
+ let end = bytes.byteLength === 0 ? 0 : 8;
1368
+ let slabLength = 0;
1369
+ let small = 0;
1370
+ for (const { cardinality, kind, offset } of layout) {
1371
+ if (kind === ARRAY) {
1372
+ slabLength += cardinality;
1373
+ small++;
1374
+ } else if (kind !== BITMAP) {
1375
+ slabLength += 2 * view.getUint16(offset, true);
1376
+ small++;
1377
+ }
1378
+ }
1379
+ const own = LITTLE_ENDIAN && bytes.byteOffset === 0 && bytes.buffer instanceof ArrayBuffer && bytes.buffer.byteLength === bytes.byteLength;
1380
+ const alias = own && small === 1;
1381
+ const slab = alias ? NO_U16 : new Uint16Array(slabLength);
1382
+ let used = 0;
1383
+ for (const { key, cardinality, kind, offset } of layout) {
1384
+ keys[n] = key;
1385
+ if (kind === ARRAY) {
1386
+ if (alias && offset % 2 === 0) {
1387
+ const values = new Uint16Array(bytes.buffer, offset, cardinality);
1388
+ conts[n++] = new Container(ARRAY2, values, 0, cardinality, cardinality, false);
1389
+ } else {
1390
+ const into = alias ? new Uint16Array(cardinality) : slab;
1391
+ getU16s(bytes, view, offset, into, alias ? 0 : used, cardinality);
1392
+ conts[n++] = new Container(
1393
+ ARRAY2,
1394
+ into,
1395
+ alias ? 0 : used,
1396
+ cardinality,
1397
+ cardinality,
1398
+ small > 1
1399
+ );
1400
+ used += cardinality;
1401
+ }
1402
+ end = offset + 2 * cardinality;
1403
+ } else if (kind === BITMAP) {
1404
+ let words;
1405
+ if (own && offset % 4 === 0) {
1406
+ words = new Uint32Array(bytes.buffer, offset, WORDS);
1407
+ } else {
1408
+ words = new Uint32Array(WORDS);
1409
+ if (LITTLE_ENDIAN) {
1410
+ new Uint8Array(words.buffer).set(bytes.subarray(offset, offset + BITSET_BYTES));
1411
+ } else {
1412
+ for (let i = 0; i < WORDS; i++) words[i] = view.getUint32(offset + 4 * i, true);
1413
+ }
1414
+ }
1415
+ conts[n++] = bitsetContainer(words, cardinality);
1416
+ end = offset + BITSET_BYTES;
1417
+ } else {
1418
+ const runs = view.getUint16(offset, true);
1419
+ if (alias && (offset + 2) % 2 === 0) {
1420
+ const pairs = new Uint16Array(bytes.buffer, offset + 2, 2 * runs);
1421
+ conts[n++] = new Container(RUN2, pairs, 0, runs, cardinality, false);
1422
+ } else {
1423
+ const into = alias ? new Uint16Array(2 * runs) : slab;
1424
+ getU16s(bytes, view, offset + 2, into, alias ? 0 : used, 2 * runs);
1425
+ conts[n++] = new Container(RUN2, into, alias ? 0 : used, runs, cardinality, small > 1);
1426
+ used += 2 * runs;
1427
+ }
1428
+ end = offset + 2 + 4 * runs;
1429
+ }
1430
+ }
1431
+ return { keys, conts, end };
1432
+ }
1433
+ var NO_U16 = new Uint16Array(0);
1434
+ function getU16s(bytes, view, at, slab, to, count) {
1435
+ if (LITTLE_ENDIAN) {
1436
+ new Uint8Array(slab.buffer, 2 * to, 2 * count).set(bytes.subarray(at, at + 2 * count));
1437
+ return;
1438
+ }
1439
+ for (let i = 0; i < count; i++) slab[to + i] = view.getUint16(at + 2 * i, true);
1440
+ }
1441
+ function trailingBytes(length, end) {
1442
+ return new IntegrityError2(
1443
+ `portable roaring: ${length - end} bytes follow the bitmap's last container, which ends at byte ${end}. One buffer holds one bitmap: to load several as one segment, combine them first and serialize the result.`
1444
+ );
1445
+ }
1446
+
1447
+ // src/ts-roaring/bitmap.ts
1448
+ var MAX_ID = 4294967295;
1449
+ function isId(value) {
1450
+ return Number.isInteger(value) && value >= 0 && value <= MAX_ID;
1451
+ }
1452
+ function badId(value) {
1453
+ return new ValidationError2(`${String(value)} is not an integer from 0 to ${MAX_ID}`);
1454
+ }
1455
+ function checkedId(value) {
1456
+ if (!isId(value)) throw badId(value);
1457
+ return value;
1458
+ }
1459
+ function collect(values) {
1460
+ if (values instanceof Uint32Array) return values;
1461
+ if (Array.isArray(values)) {
1462
+ const list = values;
1463
+ const out2 = new Uint32Array(list.length);
1464
+ for (let i = 0; i < list.length; i++) {
1465
+ const v = list[i];
1466
+ if (v >>> 0 !== v) throw badId(v);
1467
+ out2[i] = v;
1468
+ }
1469
+ return out2;
1470
+ }
1471
+ let out = new Uint32Array(1024);
1472
+ let n = 0;
1473
+ for (const v of values) {
1474
+ if (n === out.length) {
1475
+ const grown = new Uint32Array(2 * n);
1476
+ grown.set(out);
1477
+ out = grown;
1478
+ }
1479
+ out[n++] = checkedId(v);
1480
+ }
1481
+ return out.subarray(0, n);
1482
+ }
1483
+ function collectLenient(values) {
1484
+ const list = Array.isArray(values) ? values : Array.from(values);
1485
+ const out = new Uint32Array(list.length);
1486
+ let n = 0;
1487
+ for (let i = 0; i < list.length; i++) {
1488
+ const v = list[i];
1489
+ if (v >>> 0 === v) out[n++] = v;
1490
+ }
1491
+ return out.subarray(0, n);
1492
+ }
1493
+ function sortedIds(ids, owned) {
1494
+ for (let i = 1; i < ids.length; i++) {
1495
+ if (ids[i - 1] > ids[i]) return (owned ? ids : ids.slice()).sort();
1496
+ }
1497
+ return ids;
1498
+ }
1499
+ function lowerBound2(keys, key, from = 0) {
1500
+ let lo = from;
1501
+ let hi = keys.length;
1502
+ while (lo < hi) {
1503
+ const mid = lo + hi >>> 1;
1504
+ if (keys[mid] < key) lo = mid + 1;
1505
+ else hi = mid;
1506
+ }
1507
+ return lo;
1508
+ }
1509
+ function gallopKeys(keys, key, from) {
1510
+ let step = 1;
1511
+ let lo = from;
1512
+ let hi = from;
1513
+ while (hi < keys.length && keys[hi] < key) {
1514
+ lo = hi + 1;
1515
+ hi += step;
1516
+ step *= 2;
1517
+ }
1518
+ return lowerBoundIn(keys, key, lo, Math.min(hi, keys.length));
1519
+ }
1520
+ function lowerBoundIn(keys, key, from, to) {
1521
+ let lo = from;
1522
+ let hi = to;
1523
+ while (lo < hi) {
1524
+ const mid = lo + hi >>> 1;
1525
+ if (keys[mid] < key) lo = mid + 1;
1526
+ else hi = mid;
1527
+ }
1528
+ return lo;
1529
+ }
1530
+ var OR = 0;
1531
+ var AND = 1;
1532
+ var AND_NOT = 2;
1533
+ function combineContainers(op, a, b) {
1534
+ if (op === OR) return containerOr(a, b, !a.shared);
1535
+ if (op === AND) return containerAnd(a, b, !a.shared);
1536
+ return containerAndNot(a, b, !a.shared);
1537
+ }
1538
+ var TsBitmap = class _TsBitmap {
1539
+ #keys;
1540
+ #conts;
1541
+ #size;
1542
+ constructor(keys, conts, size) {
1543
+ this.#keys = keys;
1544
+ this.#conts = conts;
1545
+ this.#size = size;
347
1546
  }
348
1547
  static empty() {
349
- return new _SafeBitmap(new RoaringBitmap32());
1548
+ return new _TsBitmap([], [], 0);
350
1549
  }
351
1550
  static fromValues(values) {
352
- return new _SafeBitmap(new RoaringBitmap32(values));
1551
+ const bitmap = _TsBitmap.empty();
1552
+ bitmap.addMany(values);
1553
+ return bitmap;
353
1554
  }
354
1555
  /**
355
- * Cap the size, check the structure, then deserialize with the **portable** format.
356
- * Throws `IntegrityError` if the input exceeds `maxBytes`, is not a well-formed portable bitmap, or fails to
357
- * decode — the native addon is never handed unbounded, malformed or unsafe-format input. With `whole`, bytes
358
- * after the bitmap's last container are refused too; without it they are ignored, as the native decoder ignores
359
- * them.
1556
+ * Cap the size, check the structure, then build the containers. With `whole`, bytes after the last container are
1557
+ * refused too; without it they are ignored.
360
1558
  *
361
- * The structural check is what makes the decoded bitmap's answers mean anything. The native deserializer
362
- * bounds its reads and checks nothing else, so bytes of the right length and the wrong shape (containers or
363
- * values out of order, overlapping runs, a cardinality that disagrees with the bits) decode into a bitmap
364
- * whose `maximum()`, `has()` and `size` are wrong, and some of those shapes crash the process when used.
1559
+ * @throws {IntegrityError} if the input exceeds `maxBytes`, is not a well-formed portable bitmap, or (with `whole`)
1560
+ * has bytes after it.
365
1561
  */
366
1562
  static safeDeserialize(bytes, maxBytes, options = {}) {
367
1563
  if (bytes.length > maxBytes) {
368
- throw new IntegrityError2(`serialized bitmap is ${bytes.length}B, exceeds cap ${maxBytes}B`);
1564
+ throw new IntegrityError3(`serialized bitmap is ${bytes.length}B, exceeds cap ${maxBytes}B`);
369
1565
  }
370
- const end = checkPortableLayout(bytes);
1566
+ const { keys, conts, end } = decodeContainers(bytes);
371
1567
  if (options.whole === true && end !== bytes.byteLength) {
372
- throw new IntegrityError2(
373
- `portable roaring: ${bytes.byteLength - end} bytes follow the bitmap's last container, which ends at byte ${end}. One buffer holds one bitmap: to load several as one segment, combine them first (RoaringBitmap32.orMany) and serialize the result.`
374
- );
375
- }
376
- try {
377
- return new _SafeBitmap(RoaringBitmap32.deserialize(bytes, DeserializationFormat.portable));
378
- } catch (err) {
379
- throw new IntegrityError2(`failed to deserialize bitmap: ${err.message}`);
1568
+ throw trailingBytes(bytes.byteLength, end);
380
1569
  }
1570
+ let size = 0;
1571
+ for (let i = 0; i < conts.length; i++) size += conts[i].card;
1572
+ return new _TsBitmap(keys, conts, size);
381
1573
  }
382
1574
  serialize() {
383
- return this.bitmap.serialize(SerializationFormat.portable);
1575
+ return serializeContainers(this.#keys, this.#conts);
384
1576
  }
385
- /**
386
- * Convert containers to run-encoding where that is smaller. Representation only — membership is untouched, and
387
- * the portable format still round-trips through {@link RoaringCodec.safeDeserialize}.
388
- *
389
- * Roaring's third container type is a RUN, and no implementation selects it on its own: it takes an explicit
390
- * `runOptimize()` pass. Nothing here made that call, so run-shaped ids paid array or bitset prices — measured
391
- * at **570×** for a contiguous 1M-id range (128.1 KiB → 0.2 KiB) and **63×** for a 2,000-run shape
392
- * (536.5 KiB → 8.5 KiB). Sparse ids come out byte-identical, so this is never a losing trade; roaring keeps
393
- * whichever encoding is smaller per container.
394
- *
395
- * Those two factors are THIS CALL's own before/after on the same ids. They are not the ones the site quotes
396
- * (543× and 63×) — those compare the optimized encoding against the best *fixed* representation at its floor,
397
- * a different baseline that happens to land near 63× on the run shape too. `pnpm bench:encoding` prints both
398
- * columns; don't carry a figure between them without checking which denominator it had.
399
- *
400
- * Called only when writing an immutable objects generation — see {@link CodecBitmap.optimize} for why the read
401
- * path deliberately does not.
402
- *
403
- * CANONICAL, which `runOptimize()` alone is not. Where a container's run and array encodings are the same size
404
- * (cardinality = 2 × runs + 1: three values in one run, five in two), CRoaring keeps whichever kind the
405
- * container already has. A chunk built from ids starts as an array and stays one; the same set reached through
406
- * `addRange`, an earlier `runOptimize()` or an operation over run containers is a run, and serializes to other
407
- * bytes. Undoing run compression first starts every container where one built from ids starts, so the bytes
408
- * depend on membership alone. On a bitmap built from ids there is nothing to undo.
409
- */
1577
+ /** Re-encode each container canonically; membership is untouched. */
410
1578
  optimize() {
411
- this.bitmap.removeRunCompression();
412
- this.bitmap.runOptimize();
1579
+ const conts = this.#conts;
1580
+ for (let i = 0; i < conts.length; i++) conts[i] = optimize(conts[i]);
413
1581
  }
414
1582
  /**
415
- * This set as storage chunks, cut from its own containers: {@link optimize} and one `serialize` when called, then
416
- * a lazy header walk that copies one container out per step (`containerPayloads`). Per container and per byte,
417
- * never per id, and the payloads are the ones {@link SafeBitmap.fromValues} of each chunk's low 16 bits would
418
- * serialize to. The walk trusts the bytes it cuts because the native serializer wrote them, from a bitmap that
419
- * passed the structural check when it was decoded.
1583
+ * The set as storage chunks: each payload is the portable bytes of a one-container bitmap holding that chunk's low 16
1584
+ * bits, optimized the way {@link optimize} does. Nothing is built until a chunk is asked for, so a writer that yields
1585
+ * between chunks runs this in slices. The call snapshots the containers and marks each shared, so a change to the
1586
+ * bitmap while the chunks are read copies a container instead of altering what the chunks will say. The bitmap's own
1587
+ * containers are not optimized by it.
420
1588
  */
421
1589
  encodeChunks() {
422
- this.optimize();
423
- return containerPayloads(this.serialize());
1590
+ const keys = this.#keys.slice();
1591
+ const conts = this.#conts.slice();
1592
+ for (let i = 0; i < conts.length; i++) conts[i].shared = true;
1593
+ return {
1594
+ *[Symbol.iterator]() {
1595
+ for (let i = 0; i < conts.length; i++) {
1596
+ const c = optimize(conts[i]);
1597
+ yield {
1598
+ chunkKey: keys[i],
1599
+ payload: serializeContainers([0], [c]),
1600
+ cardinality: c.card
1601
+ };
1602
+ }
1603
+ }
1604
+ };
424
1605
  }
425
- /**
426
- * Largest value, or `undefined` when empty. O(1) — roaring reads it off the last container, so the engine's
427
- * per-chunk range assertion costs one call per chunk rather than a walk per id. The last container holds the
428
- * largest value only because {@link SafeBitmap.safeDeserialize} refuses bytes whose containers or values are
429
- * out of order.
430
- */
431
1606
  maximum() {
432
- return this.bitmap.isEmpty ? void 0 : this.bitmap.maximum();
1607
+ const last = this.#conts.length - 1;
1608
+ if (last < 0) return void 0;
1609
+ return this.#keys[last] * 65536 + containerMax(this.#conts[last]);
433
1610
  }
434
1611
  add(value) {
435
- this.bitmap.add(value);
1612
+ checkedId(value);
1613
+ const key = value >>> 16;
1614
+ const low = value & 65535;
1615
+ const at = lowerBound2(this.#keys, key);
1616
+ const found = this.#keys[at] === key;
1617
+ if (!found) {
1618
+ this.#insert(at, key, arrayContainer(Uint16Array.of(low), 1));
1619
+ this.#size++;
1620
+ return;
1621
+ }
1622
+ const before = this.#conts[at];
1623
+ const after = containerAdd(before, low);
1624
+ this.#conts[at] = after;
1625
+ this.#size += after.card - before.card;
436
1626
  }
1627
+ /**
1628
+ * Add the ids. They are grouped by key in ascending order, so each container is touched once, a key already held is
1629
+ * merged where it is, and the new keys are put in with one pass over the key list however many there are.
1630
+ */
437
1631
  addMany(values) {
438
- this.bitmap.addMany(values);
1632
+ const ids = sortedIds(collect(values), !(values instanceof Uint32Array));
1633
+ const fresh = [];
1634
+ let at = 0;
1635
+ for (let i = 0; i < ids.length; ) {
1636
+ const key = ids[i] >>> 16;
1637
+ let end = i + 1;
1638
+ while (end < ids.length && ids[end] >>> 16 === key) end++;
1639
+ const group = fromSortedIds(ids, i, end);
1640
+ i = end;
1641
+ at = gallopKeys(this.#keys, key, at);
1642
+ if (this.#keys[at] === key) {
1643
+ const before = this.#conts[at];
1644
+ const after = containerOr(before, group, !before.shared);
1645
+ this.#conts[at] = after;
1646
+ this.#size += after.card - before.card;
1647
+ } else {
1648
+ fresh.push({ key, group });
1649
+ this.#size += group.card;
1650
+ }
1651
+ }
1652
+ if (fresh.length > 0) this.#insertAll(fresh);
439
1653
  }
440
1654
  remove(value) {
441
- this.bitmap.remove(value);
1655
+ if (!isId(value)) return;
1656
+ const key = value >>> 16;
1657
+ const at = lowerBound2(this.#keys, key);
1658
+ if (this.#keys[at] !== key) return;
1659
+ const before = this.#conts[at];
1660
+ const after = containerRemove(before, value & 65535);
1661
+ if (after === null) {
1662
+ this.#keys.splice(at, 1);
1663
+ this.#conts.splice(at, 1);
1664
+ this.#size -= before.card;
1665
+ return;
1666
+ }
1667
+ this.#conts[at] = after;
1668
+ this.#size += after.card - before.card;
442
1669
  }
1670
+ /** Remove the ids (anything that is not an id is ignored), grouped by key; the keys left empty go in one pass. */
443
1671
  removeMany(values) {
444
- this.bitmap.removeMany(values);
1672
+ const ids = sortedIds(collectLenient(values), true);
1673
+ const keys = this.#keys;
1674
+ const conts = this.#conts;
1675
+ let at = 0;
1676
+ let emptied = 0;
1677
+ for (let i = 0; i < ids.length; ) {
1678
+ const key = ids[i] >>> 16;
1679
+ let end = i + 1;
1680
+ while (end < ids.length && ids[end] >>> 16 === key) end++;
1681
+ const from = i;
1682
+ i = end;
1683
+ at = gallopKeys(keys, key, at);
1684
+ if (keys[at] !== key) continue;
1685
+ const before = conts[at];
1686
+ if (before.card === 0) continue;
1687
+ const after = containerAndNot(before, fromSortedIds(ids, from, end), !before.shared);
1688
+ this.#size -= before.card - (after === null ? 0 : after.card);
1689
+ if (after === null) {
1690
+ conts[at] = EMPTIED;
1691
+ emptied++;
1692
+ } else {
1693
+ conts[at] = after;
1694
+ }
1695
+ }
1696
+ if (emptied > 0) this.#dropEmptied();
445
1697
  }
446
1698
  has(value) {
447
- return this.bitmap.has(value);
1699
+ if (!isId(value)) return false;
1700
+ const key = value >>> 16;
1701
+ const at = lowerBound2(this.#keys, key);
1702
+ return this.#keys[at] === key && containerHas(this.#conts[at], value & 65535);
448
1703
  }
449
1704
  get size() {
450
- return this.bitmap.size;
1705
+ return this.#size;
451
1706
  }
452
1707
  get isEmpty() {
453
- return this.bitmap.isEmpty;
1708
+ return this.#size === 0;
454
1709
  }
455
1710
  clone() {
456
- return new _SafeBitmap(this.bitmap.clone());
1711
+ const conts = new Array(this.#conts.length);
1712
+ for (let i = 0; i < conts.length; i++) {
1713
+ const c = this.#conts[i];
1714
+ c.shared = true;
1715
+ conts[i] = c;
1716
+ }
1717
+ return new _TsBitmap(this.#keys.slice(), conts, this.#size);
457
1718
  }
458
- // The binary set ops take the `CodecBitmap` interface type (per the seam), but a single store is
459
- // single-codec (homogeneity contract), so `other` is always a `SafeBitmap` here — reach its private
460
- // `bitmap` (accessible on same-class instances) for the native op.
461
- /** In-place union: `this = this ∪ other`. */
462
1719
  orInPlace(other) {
463
- this.bitmap.orInPlace(other.bitmap);
1720
+ this.#combine(_TsBitmap.#of(other), OR);
464
1721
  }
465
- /** In-place difference: `this = this \ other`. */
466
- andNotInPlace(other) {
467
- this.bitmap.andNotInPlace(other.bitmap);
468
- }
469
- /** In-place intersection: `this = this ∩ other`. */
470
1722
  andInPlace(other) {
471
- this.bitmap.andInPlace(other.bitmap);
1723
+ this.#combine(_TsBitmap.#of(other), AND);
1724
+ }
1725
+ andNotInPlace(other) {
1726
+ this.#combine(_TsBitmap.#of(other), AND_NOT);
472
1727
  }
473
- /** Ascending iterator over the set values. */
474
1728
  [Symbol.iterator]() {
475
- return this.bitmap[Symbol.iterator]();
1729
+ return new BitmapIterator(this.#keys, this.#conts);
476
1730
  }
477
1731
  toArray() {
478
- return this.bitmap.toArray();
1732
+ return Array.from(this.toUint32Array());
479
1733
  }
480
- /** The values as one fresh ascending `Uint32Array`, exported natively. */
1734
+ /** The ids as a new ascending `Uint32Array`. */
481
1735
  toUint32Array() {
482
- return this.bitmap.toUint32Array();
1736
+ const out = new Uint32Array(this.#size);
1737
+ let at = 0;
1738
+ for (let i = 0; i < this.#conts.length; i++) {
1739
+ at = appendIds(this.#conts[i], out, at, this.#keys[i] * 65536);
1740
+ }
1741
+ return out;
483
1742
  }
484
- };
485
- function bitmapAsLoadInput(input) {
486
- return input instanceof RoaringBitmap32 || input instanceof ReadonlyRoaringView ? { bitmap: input } : input;
487
- }
488
- var roaringCodec = {
489
- empty: () => SafeBitmap.empty(),
490
- fromValues: (values) => SafeBitmap.fromValues(values),
491
- safeDeserialize: (bytes, maxBytes, options) => SafeBitmap.safeDeserialize(bytes, maxBytes, options),
492
- owns: (bitmap) => bitmap instanceof SafeBitmap
493
- };
494
- var ReadonlyRoaringView = class {
495
- #bitmap;
496
- constructor(bitmap) {
497
- this.#bitmap = bitmap;
1743
+ static #of(other) {
1744
+ if (!(other instanceof _TsBitmap)) {
1745
+ throw new ValidationError2("a TypeScript roaring bitmap combines only with another one");
1746
+ }
1747
+ return other;
498
1748
  }
499
- get size() {
500
- return this.#bitmap.size;
1749
+ #insert(at, key, container) {
1750
+ if (at === this.#keys.length) {
1751
+ this.#keys.push(key);
1752
+ this.#conts.push(container);
1753
+ } else {
1754
+ this.#keys.splice(at, 0, key);
1755
+ this.#conts.splice(at, 0, container);
1756
+ }
501
1757
  }
502
- has(id) {
503
- return this.#bitmap.has(id);
1758
+ /** Put the new keys, ascending and none held, in: after the last key by pushing, else in one merge pass. */
1759
+ #insertAll(fresh) {
1760
+ const keys = this.#keys;
1761
+ const conts = this.#conts;
1762
+ if (keys.length === 0 || keys[keys.length - 1] < fresh[0].key) {
1763
+ for (const { key, group } of fresh) {
1764
+ keys.push(key);
1765
+ conts.push(group);
1766
+ }
1767
+ return;
1768
+ }
1769
+ const outKeys = [];
1770
+ const outConts = [];
1771
+ let i = 0;
1772
+ let j = 0;
1773
+ while (i < keys.length || j < fresh.length) {
1774
+ if (j === fresh.length || i < keys.length && keys[i] < fresh[j].key) {
1775
+ outKeys.push(keys[i]);
1776
+ outConts.push(conts[i++]);
1777
+ } else {
1778
+ const next = fresh[j++];
1779
+ outKeys.push(next.key);
1780
+ outConts.push(next.group);
1781
+ }
1782
+ }
1783
+ this.#keys = outKeys;
1784
+ this.#conts = outConts;
1785
+ }
1786
+ /** Remove the keys whose container was emptied by {@link removeMany}, in one pass. */
1787
+ #dropEmptied() {
1788
+ let kept = 0;
1789
+ for (let i = 0; i < this.#conts.length; i++) {
1790
+ if (this.#conts[i] === EMPTIED) continue;
1791
+ this.#keys[kept] = this.#keys[i];
1792
+ this.#conts[kept++] = this.#conts[i];
1793
+ }
1794
+ this.#keys.length = kept;
1795
+ this.#conts.length = kept;
504
1796
  }
505
- [Symbol.iterator]() {
506
- return this.#bitmap[Symbol.iterator]();
507
- }
508
- /** The portable bytes, for exactly the argument `'portable'`; any other call is a `ValidationError`. */
509
- serialize(...args) {
510
- if (args.length !== 1 || args[0] !== "portable") {
511
- const got = args.length === 0 ? "no argument" : args.map((a) => typeof a === "string" ? `'${a}'` : typeof a).join(", ");
512
- throw new ValidationError2(
513
- `a decoded bitmap serializes only as serialize('portable'); got ${got}`
514
- );
1797
+ /**
1798
+ * Walk both key lists and rebuild this one: where both hold a key, the combine of the two containers; where only this
1799
+ * does, its container, unless the operation is an intersection; where only `that` does, a copy of its container for a
1800
+ * union and nothing otherwise. A combine that leaves no value drops the key. An intersection jumps over a stretch of
1801
+ * keys the other side lacks by doubling steps, so a few keys against many cost the few.
1802
+ */
1803
+ #combine(that, op) {
1804
+ const a = this.#keys;
1805
+ const b = that.#keys;
1806
+ const ca = this.#conts;
1807
+ const cb = that.#conts;
1808
+ const keys = [];
1809
+ const conts = [];
1810
+ let size = 0;
1811
+ let i = 0;
1812
+ let j = 0;
1813
+ while (i < a.length && j < b.length) {
1814
+ const ka = a[i];
1815
+ const kb = b[j];
1816
+ if (ka === kb) {
1817
+ const c = combineContainers(op, ca[i++], cb[j++]);
1818
+ if (c !== null) {
1819
+ keys.push(ka);
1820
+ conts.push(c);
1821
+ size += c.card;
1822
+ }
1823
+ } else if (ka < kb) {
1824
+ if (op === AND) {
1825
+ i = gallopKeys(a, kb, i + 1);
1826
+ } else {
1827
+ keys.push(ka);
1828
+ conts.push(ca[i]);
1829
+ size += ca[i++].card;
1830
+ }
1831
+ } else if (op === AND) {
1832
+ j = gallopKeys(b, ka, j + 1);
1833
+ } else {
1834
+ if (op === OR) {
1835
+ keys.push(kb);
1836
+ conts.push(cloneContainer(cb[j]));
1837
+ size += cb[j].card;
1838
+ }
1839
+ j++;
1840
+ }
1841
+ }
1842
+ if (op !== AND) {
1843
+ for (; i < a.length; i++) {
1844
+ keys.push(a[i]);
1845
+ conts.push(ca[i]);
1846
+ size += ca[i].card;
1847
+ }
515
1848
  }
516
- return this.#bitmap.serialize();
1849
+ if (op === OR) {
1850
+ for (; j < b.length; j++) {
1851
+ keys.push(b[j]);
1852
+ conts.push(cloneContainer(cb[j]));
1853
+ size += cb[j].card;
1854
+ }
1855
+ }
1856
+ this.#keys = keys;
1857
+ this.#conts = conts;
1858
+ this.#size = size;
517
1859
  }
518
1860
  };
1861
+ var EMPTIED = arrayContainer(new Uint16Array(0), 0);
1862
+ var tsRoaringCodec = {
1863
+ empty: () => TsBitmap.empty(),
1864
+ fromValues: (values) => TsBitmap.fromValues(values),
1865
+ safeDeserialize: (bytes, maxBytes, options) => TsBitmap.safeDeserialize(bytes, maxBytes, options),
1866
+ owns: (bitmap) => bitmap instanceof TsBitmap,
1867
+ intersectSmallestFirst: true
1868
+ };
1869
+
1870
+ // src/roaring-codec.ts
1871
+ function bitmapAsLoadInput(input) {
1872
+ if (typeof input !== "object" || input === null) return input;
1873
+ const tag = Object.prototype.toString.call(input).slice(8, -1);
1874
+ if (tag === "Uint8Array" || tag === "Uint8ClampedArray") return input;
1875
+ return Symbol.iterator in input && typeof input.serialize === "function" ? { bitmap: input } : input;
1876
+ }
1877
+ var activeCodec = tsRoaringCodec;
1878
+ function flagshipCodec() {
1879
+ return activeCodec;
1880
+ }
519
1881
 
520
1882
  // src/system-clock.ts
521
1883
  var SystemClock = class {
@@ -655,7 +2017,7 @@ import {
655
2017
  DEFAULT_RETRY_POLICY,
656
2018
  NOOP_METRICS,
657
2019
  RetryingStorageChunkSource,
658
- ValidationError as ValidationError3,
2020
+ ValidationError as ValidationError4,
659
2021
  isStorageBackend
660
2022
  } from "@cloudbitmaps/core";
661
2023
  function resolveRetryPolicy(partial) {
@@ -679,7 +2041,7 @@ function wireStore(options, clock, rng, metrics) {
679
2041
  if (options.retry !== false) {
680
2042
  const { onRetry: userOnRetry, ...ov } = options.retry ?? {};
681
2043
  if (userOnRetry !== void 0 && typeof userOnRetry !== "function") {
682
- throw new ValidationError3("retry.onRetry must be a function");
2044
+ throw new ValidationError4("retry.onRetry must be a function");
683
2045
  }
684
2046
  retryOptions = {
685
2047
  clock,
@@ -710,7 +2072,7 @@ function wireStore(options, clock, rng, metrics) {
710
2072
  function resolveStorageSource(options, clock) {
711
2073
  const storage = options.storage;
712
2074
  if (storage === null || typeof storage !== "object") {
713
- throw new ValidationError3(
2075
+ throw new ValidationError4(
714
2076
  "`storage` must be a StorageBackend, an IStorageDriver, or a StorageChunkSource"
715
2077
  );
716
2078
  }
@@ -720,14 +2082,14 @@ function resolveStorageSource(options, clock) {
720
2082
  const hasPutImmutable = typeof storage.putImmutable === "function";
721
2083
  const isBackend = isStorageBackend(storage);
722
2084
  if (isBackend && (hasGetChunk || hasPutImmutable)) {
723
- throw new ValidationError3(
2085
+ throw new ValidationError4(
724
2086
  `\`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.`
725
2087
  );
726
2088
  }
727
2089
  const hasStorageHalf = isObject(asBackend.storage);
728
2090
  const hasRegistryHalf = isObject(asBackend.registry);
729
2091
  if (!isBackend && hasPutImmutable && hasRegistryHalf) {
730
- throw new ValidationError3(
2092
+ throw new ValidationError4(
731
2093
  "`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`."
732
2094
  );
733
2095
  }
@@ -736,11 +2098,11 @@ function resolveStorageSource(options, clock) {
736
2098
  const registryOk = typeof asBackend.registry.compareAndSwap === "function";
737
2099
  if (!storageOk || !registryOk) {
738
2100
  const bad = !storageOk ? "`storage` half is not an IStorageDriver (no `putImmutable`)" : "`registry` half is not an IRegistryDriver (no `compareAndSwap`)";
739
- throw new ValidationError3(
2101
+ throw new ValidationError4(
740
2102
  "`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`."
741
2103
  );
742
2104
  }
743
- throw new ValidationError3(
2105
+ throw new ValidationError4(
744
2106
  "`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."
745
2107
  );
746
2108
  }
@@ -761,18 +2123,18 @@ function resolveStorageSource(options, clock) {
761
2123
  };
762
2124
  }
763
2125
  if (hasGetChunk && hasPutImmutable) {
764
- throw new ValidationError3(
2126
+ throw new ValidationError4(
765
2127
  "`storage` exposes both `getChunk` and `putImmutable` \u2014 ambiguous; pass a StorageBackend, an IStorageDriver, or a StorageChunkSource, not a hybrid"
766
2128
  );
767
2129
  }
768
2130
  if (!hasGetChunk && !hasPutImmutable) {
769
- throw new ValidationError3(
2131
+ throw new ValidationError4(
770
2132
  "`storage` must be a StorageBackend, an IStorageDriver, or a StorageChunkSource"
771
2133
  );
772
2134
  }
773
2135
  if (hasGetChunk) {
774
2136
  if (options.encryption?.keystore !== void 0 || options.encryption?.required === true) {
775
- throw new ValidationError3(
2137
+ throw new ValidationError4(
776
2138
  "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"
777
2139
  );
778
2140
  }
@@ -794,32 +2156,32 @@ function resolveStorageSource(options, clock) {
794
2156
  }
795
2157
 
796
2158
  // src/options.ts
797
- import { ValidationError as ValidationError4 } from "@cloudbitmaps/core";
2159
+ import { ValidationError as ValidationError5 } from "@cloudbitmaps/core";
798
2160
  var keysOf = () => (keys) => keys;
799
2161
  var kindOf = (v) => v === null ? "null" : Array.isArray(v) ? "an array" : `a ${typeof v}`;
800
2162
  function optionsError(options, op, known, booleans = [], misplaced = []) {
801
2163
  if (options === void 0 || options === null) return void 0;
802
2164
  if (typeof options !== "object" || Array.isArray(options)) {
803
- return new ValidationError4(`${op}: options must be an object; got ${kindOf(options)}`);
2165
+ return new ValidationError5(`${op}: options must be an object; got ${kindOf(options)}`);
804
2166
  }
805
2167
  const bag = options;
806
2168
  const unknown = Object.keys(bag).filter((k) => !known.includes(k) && bag[k] !== void 0);
807
2169
  for (const k of misplaced) if (!unknown.includes(k) && bag[k] !== void 0) unknown.push(k);
808
2170
  if (unknown.length > 0) {
809
- return new ValidationError4(
2171
+ return new ValidationError5(
810
2172
  `${op}: unknown option${unknown.length > 1 ? "s" : ""} ${unknown.map((k) => `"${k}"`).join(", ")}; it takes { ${known.join(", ")} }`
811
2173
  );
812
2174
  }
813
2175
  const audit = bag.audit;
814
2176
  if (audit !== void 0 && audit !== null && typeof audit.onEvent !== "function") {
815
- return new ValidationError4(
2177
+ return new ValidationError5(
816
2178
  `${op}: audit must be a sink with an onEvent(event) method, such as a RecordingAuditSink`
817
2179
  );
818
2180
  }
819
2181
  for (const name of booleans) {
820
2182
  const v = bag[name];
821
2183
  if (v !== void 0 && typeof v !== "boolean") {
822
- return new ValidationError4(`${op}: \`${name}\` must be a boolean; got ${kindOf(v)}`);
2184
+ return new ValidationError5(`${op}: \`${name}\` must be a boolean; got ${kindOf(v)}`);
823
2185
  }
824
2186
  }
825
2187
  return void 0;
@@ -844,9 +2206,9 @@ import {
844
2206
  excludingReservedRows as excludingReservedRows2,
845
2207
  readRetentionPolicy,
846
2208
  CloudRoaringError,
847
- ValidationError as ValidationError6,
2209
+ ValidationError as ValidationError7,
848
2210
  WriteConflictError as WriteConflictError2,
849
- IntegrityError as IntegrityError3,
2211
+ IntegrityError as IntegrityError4,
850
2212
  NotFoundError as NotFoundError2,
851
2213
  UnsupportedError as UnsupportedError3,
852
2214
  CapabilityError,
@@ -868,7 +2230,7 @@ var SystemRng = class {
868
2230
  };
869
2231
  function validateRef(ref, verb) {
870
2232
  if (typeof ref !== "object" || ref === null) {
871
- throw new ValidationError5(
2233
+ throw new ValidationError6(
872
2234
  "a segment ref is an object such as { segment: 'name' }; store.segment() takes the bare name"
873
2235
  );
874
2236
  }
@@ -889,7 +2251,7 @@ function validateConcurrency(concurrency) {
889
2251
  function requireScope(options, op) {
890
2252
  if (options.namespace !== void 0) {
891
2253
  if (typeof options.namespace !== "string") {
892
- throw new ValidationError5(
2254
+ throw new ValidationError6(
893
2255
  `${op}: namespace must be a string; got ${kindOf(options.namespace)}`
894
2256
  );
895
2257
  }
@@ -897,12 +2259,12 @@ function requireScope(options, op) {
897
2259
  }
898
2260
  refuseReservedNamespace(options.namespace);
899
2261
  if (options.namespace !== void 0 && options.allNamespaces === true) {
900
- throw new ValidationError5(
2262
+ throw new ValidationError6(
901
2263
  `${op}: pass a namespace or { allNamespaces: true }, not both: with both, it is unclear whether to scan one namespace or every one`
902
2264
  );
903
2265
  }
904
2266
  if (options.namespace === void 0 && options.allNamespaces !== true) {
905
- throw new ValidationError5(
2267
+ throw new ValidationError6(
906
2268
  `${op} scans the global id space across all namespaces \u2014 pass an explicit \`namespace\`, or \`{ allNamespaces: true }\` to intentionally sweep the whole fleet`
907
2269
  );
908
2270
  }
@@ -1010,16 +2372,16 @@ var originOf;
1010
2372
  function assertOneStore(verb, role, h, origin) {
1011
2373
  if (h instanceof Segment) {
1012
2374
  if (originOf(h) === origin) return;
1013
- throw new ValidationError5(
2375
+ throw new ValidationError6(
1014
2376
  `${verb}: ${role} belongs to another store; combine segments of one store: open each with this store's segment()`
1015
2377
  );
1016
2378
  }
1017
2379
  if (typeof h === "object" && h !== null && h[SEGMENT_BRAND] === true) {
1018
- throw new ValidationError5(
2380
+ throw new ValidationError6(
1019
2381
  `${verb}: ${role} comes from another installed copy of @cloudbitmaps/roaring, so it belongs to another store; install one copy and combine segments of one store`
1020
2382
  );
1021
2383
  }
1022
- throw new ValidationError5(`${verb}: ${role} must be a segment from this store's segment()`);
2384
+ throw new ValidationError6(`${verb}: ${role} must be a segment from this store's segment()`);
1023
2385
  }
1024
2386
  var MATERIALIZE_MANY_KEYS = [
1025
2387
  "operands",
@@ -1109,7 +2471,7 @@ var CloudRoaring = class _CloudRoaring {
1109
2471
  */
1110
2472
  static rejectUnknownOptions(options) {
1111
2473
  if (options === null || options === void 0 || typeof options !== "object") {
1112
- throw new ValidationError5(
2474
+ throw new ValidationError6(
1113
2475
  "CloudRoaring needs an options object with a `storage` key \u2014 got " + (options === null ? "null" : typeof options)
1114
2476
  );
1115
2477
  }
@@ -1127,7 +2489,7 @@ var CloudRoaring = class _CloudRoaring {
1127
2489
  const tag = Object.prototype.toString.call(value).slice(8, -1);
1128
2490
  if (typeof value !== "object" || value === null || NOT_A_GROUP[tag] !== void 0) {
1129
2491
  const got = typeof value !== "object" ? typeof value : NOT_A_GROUP[tag];
1130
- throw new ValidationError5(
2492
+ throw new ValidationError6(
1131
2493
  `CloudRoaring's \`${group}\` must be an object${offOk ? " or `false`" : ""} \u2014 got ${got}`
1132
2494
  );
1133
2495
  }
@@ -1137,7 +2499,7 @@ var CloudRoaring = class _CloudRoaring {
1137
2499
  if (unknown.length === 0) return;
1138
2500
  const takes = (keys) => keys.map((k) => `\`${k}\``).join(", ");
1139
2501
  const named = [...new Set(unknown.map((u) => u.group))];
1140
- throw new ValidationError5(
2502
+ throw new ValidationError6(
1141
2503
  `CloudRoaring does not take ${takes(unknown.map((u) => u.group === null ? u.key : `${u.group}.${u.key}`))}. ` + named.map(
1142
2504
  (g) => g === null ? `The store takes ${takes(OPTION_KEYS.top)}.` : `\`${g}\` takes ${takes(OPTION_KEYS[g])}.`
1143
2505
  ).join(" ") + " https://github.com/cloudbitmaps/cloudbitmaps/blob/main/docs/guide/api-reference.md#build-a-store--new-cloudroaringoptions"
@@ -1155,7 +2517,7 @@ var CloudRoaring = class _CloudRoaring {
1155
2517
  ];
1156
2518
  const entropy = options.seams?.entropy;
1157
2519
  if (entropy !== void 0 && typeof entropy !== "function") {
1158
- throw new ValidationError5(
2520
+ throw new ValidationError6(
1159
2521
  "CloudRoaring's `seams.entropy` must be a function `(length) => Uint8Array` returning that many random bytes"
1160
2522
  );
1161
2523
  }
@@ -1163,7 +2525,7 @@ var CloudRoaring = class _CloudRoaring {
1163
2525
  if (seam === void 0) continue;
1164
2526
  const has = (m) => seam !== null && typeof seam[m] === "function";
1165
2527
  if (seam === null || typeof seam !== "object" || !needs.every(has)) {
1166
- throw new ValidationError5(
2528
+ throw new ValidationError6(
1167
2529
  `CloudRoaring's \`${name}\` must be an object with ${needs.map((m) => `\`${m}()\``).join(" and ")}`
1168
2530
  );
1169
2531
  }
@@ -1183,7 +2545,7 @@ var CloudRoaring = class _CloudRoaring {
1183
2545
  requirePositiveInt("cache.readerMaxBytes", cache.readerMaxBytes);
1184
2546
  const ttl = cache.ttlMs;
1185
2547
  if (ttl !== void 0 && (typeof ttl !== "number" || !Number.isFinite(ttl) || ttl <= 0)) {
1186
- throw new ValidationError5(
2548
+ throw new ValidationError6(
1187
2549
  `cache.ttlMs must be a finite number above 0 (milliseconds); got ${typeof ttl === "string" ? JSON.stringify(ttl) : String(ttl)}`
1188
2550
  );
1189
2551
  }
@@ -1215,7 +2577,7 @@ var CloudRoaring = class _CloudRoaring {
1215
2577
  const deps = {
1216
2578
  storage: wired.storage,
1217
2579
  cache,
1218
- codec: roaringCodec,
2580
+ codec: flagshipCodec(),
1219
2581
  // the facade injects the flagship codec; core stays codec-agnostic
1220
2582
  clock,
1221
2583
  metrics,
@@ -1258,7 +2620,7 @@ var CloudRoaring = class _CloudRoaring {
1258
2620
  clock: this.clock,
1259
2621
  rng: this.rng,
1260
2622
  entropy: this.entropy,
1261
- codec: roaringCodec,
2623
+ codec: flagshipCodec(),
1262
2624
  // facade injects the flagship codec
1263
2625
  keystore: this.keystore,
1264
2626
  requireEncryption: this.requireEncryption,
@@ -1275,17 +2637,17 @@ var CloudRoaring = class _CloudRoaring {
1275
2637
  */
1276
2638
  segment(name, options) {
1277
2639
  if (typeof name === "object" && name !== null) {
1278
- throw new ValidationError5(
2640
+ throw new ValidationError6(
1279
2641
  Array.isArray(name) ? "segment: the name is a string, store.segment('name'), not an array" : "segment: the name is a string, not a ref: for a ref, call store.segment(ref.segment, { namespace: ref.namespace })"
1280
2642
  );
1281
2643
  }
1282
2644
  if (options !== void 0 && options !== null) {
1283
2645
  if (typeof options !== "object" || Array.isArray(options)) {
1284
- throw new ValidationError5("segment: options must be an object such as { namespace }");
2646
+ throw new ValidationError6("segment: options must be an object such as { namespace }");
1285
2647
  }
1286
2648
  const proto = Object.getPrototypeOf(options);
1287
2649
  if (proto !== null && Object.getPrototypeOf(proto) !== null) {
1288
- throw new ValidationError5(
2650
+ throw new ValidationError6(
1289
2651
  "segment: options must be a plain object such as { namespace }, not a class instance or an object built on another"
1290
2652
  );
1291
2653
  }
@@ -1293,7 +2655,7 @@ var CloudRoaring = class _CloudRoaring {
1293
2655
  (k) => k !== "namespace" && options[k] !== void 0
1294
2656
  );
1295
2657
  if (unknown.length > 0) {
1296
- throw new ValidationError5(
2658
+ throw new ValidationError6(
1297
2659
  `segment: unknown option${unknown.length > 1 ? "s" : ""} ${unknown.map((k) => `"${k}"`).join(", ")}; a handle takes { namespace } only`
1298
2660
  );
1299
2661
  }
@@ -1403,20 +2765,20 @@ var CloudRoaring = class _CloudRoaring {
1403
2765
  /** The one body of the forms above. */
1404
2766
  async materializeMany(options) {
1405
2767
  if (typeof options !== "object" || options === null) {
1406
- throw new ValidationError5(
2768
+ throw new ValidationError6(
1407
2769
  "materializeMany needs an options object with `operands`, `outputs` and `keep`"
1408
2770
  );
1409
2771
  }
1410
2772
  const epochAt = options.feed === void 0 ? 0 : this.epochNow();
1411
2773
  const unknown = unknownManyKeys(options);
1412
2774
  if (unknown.length > 0) {
1413
- throw new ValidationError5(
2775
+ throw new ValidationError6(
1414
2776
  `materializeMany: unknown option${unknown.length > 1 ? "s" : ""} ${unknown.map((k) => `"${k}"`).join(", ")}`
1415
2777
  );
1416
2778
  }
1417
2779
  const dryRunIn = options.dryRun;
1418
2780
  if (dryRunIn !== void 0 && typeof dryRunIn !== "boolean") {
1419
- throw new ValidationError5("materializeMany: dryRun must be a boolean");
2781
+ throw new ValidationError6("materializeMany: dryRun must be a boolean");
1420
2782
  }
1421
2783
  const dryRun = dryRunIn === true;
1422
2784
  const operandsIn = options.operands;
@@ -1428,7 +2790,7 @@ var CloudRoaring = class _CloudRoaring {
1428
2790
  const feedIn = options.feed;
1429
2791
  const mayBeEmptyIn = options.mayBeEmpty;
1430
2792
  if (feedIn !== void 0 && options.maxBufferedBytes === void 0) {
1431
- throw new ValidationError5(
2793
+ throw new ValidationError6(
1432
2794
  "materializeMany: maxBufferedBytes is required with a feed: the feed is read once, so the call runs as one group and the budget is what bounds it"
1433
2795
  );
1434
2796
  }
@@ -1438,15 +2800,15 @@ var CloudRoaring = class _CloudRoaring {
1438
2800
  const budgetOption = options.budget;
1439
2801
  const allowAbsentOperands = options.allowAbsentOperands;
1440
2802
  if (typeof pinOption !== "boolean")
1441
- throw new ValidationError5("materializeMany: pin must be a boolean");
2803
+ throw new ValidationError6("materializeMany: pin must be a boolean");
1442
2804
  if (allowAbsentOperands !== void 0 && typeof allowAbsentOperands !== "boolean") {
1443
- throw new ValidationError5("materializeMany: allowAbsentOperands must be a boolean");
2805
+ throw new ValidationError6("materializeMany: allowAbsentOperands must be a boolean");
1444
2806
  }
1445
2807
  if (typeof operandsIn !== "object" || operandsIn === null || Array.isArray(operandsIn)) {
1446
- throw new ValidationError5("materializeMany: operands must be an object of name to segment");
2808
+ throw new ValidationError6("materializeMany: operands must be an object of name to segment");
1447
2809
  }
1448
2810
  if (!Array.isArray(outputsIn) || outputsIn.length === 0) {
1449
- throw new ValidationError5("materializeMany: outputs must be a non-empty array");
2811
+ throw new ValidationError6("materializeMany: outputs must be a non-empty array");
1450
2812
  }
1451
2813
  const names = Object.keys(operandsIn);
1452
2814
  const handles = /* @__PURE__ */ new Map();
@@ -1457,14 +2819,14 @@ var CloudRoaring = class _CloudRoaring {
1457
2819
  }
1458
2820
  if (mayBeEmptyIn !== void 0 && feedIn === void 0) {
1459
2821
  if (!Array.isArray(mayBeEmptyIn)) {
1460
- throw new ValidationError5(
2822
+ throw new ValidationError6(
1461
2823
  "materializeMany: mayBeEmpty must be an array of fed operand names"
1462
2824
  );
1463
2825
  }
1464
2826
  if (mayBeEmptyIn.length > 0) {
1465
2827
  const first = mayBeEmptyIn[0];
1466
2828
  const what = typeof first !== "string" ? "something that is not a name" : handles.has(first) ? `"${first}", a stored operand` : `"${first}", which is not an operand of this call`;
1467
- throw new ValidationError5(
2829
+ throw new ValidationError6(
1468
2830
  `materializeMany: mayBeEmpty names ${what}; it names fed operands, and this call has no feed`
1469
2831
  );
1470
2832
  }
@@ -1474,13 +2836,13 @@ var CloudRoaring = class _CloudRoaring {
1474
2836
  const destKeys = /* @__PURE__ */ new Set();
1475
2837
  outputsIn.forEach((raw, i) => {
1476
2838
  if (typeof raw !== "object" || raw === null) {
1477
- throw new ValidationError5(`outputs[${i}] must be an object`);
2839
+ throw new ValidationError6(`outputs[${i}] must be an object`);
1478
2840
  }
1479
2841
  const bad = Object.keys(raw).filter(
1480
2842
  (k) => !MATERIALIZE_MANY_OUTPUT_KEYS.includes(k)
1481
2843
  );
1482
2844
  if (bad.length > 0) {
1483
- throw new ValidationError5(
2845
+ throw new ValidationError6(
1484
2846
  `outputs[${i}]: unknown option${bad.length > 1 ? "s" : ""} ${bad.map((k) => `"${k}"`).join(", ")}`
1485
2847
  );
1486
2848
  }
@@ -1488,12 +2850,12 @@ var CloudRoaring = class _CloudRoaring {
1488
2850
  const dest = spec.dest;
1489
2851
  assertOneStore("materializeMany", `outputs[${i}].dest`, dest, this.origin);
1490
2852
  if (operandKeys.has(dest.key())) {
1491
- throw new ValidationError5(
2853
+ throw new ValidationError6(
1492
2854
  `outputs[${i}].dest is also an operand of the call: one call is one pass over operands that do not change under it, so chain two calls`
1493
2855
  );
1494
2856
  }
1495
2857
  if (destKeys.has(dest.key())) {
1496
- throw new ValidationError5(
2858
+ throw new ValidationError6(
1497
2859
  `outputs[${i}].dest names a segment another output of the call writes`
1498
2860
  );
1499
2861
  }
@@ -1566,13 +2928,13 @@ var CloudRoaring = class _CloudRoaring {
1566
2928
  held.set(key, { at, handle });
1567
2929
  } else if (prior.at !== void 0 && at !== void 0) {
1568
2930
  if (!samePin(prior.at, at)) {
1569
- throw new ValidationError5(
2931
+ throw new ValidationError6(
1570
2932
  `materializeMany: operand "${name}" holds a segment another operand holds, ${twoPins(prior.at, at)}: one call reads a segment at one generation`
1571
2933
  );
1572
2934
  }
1573
2935
  } else if (prior.at !== void 0 || at !== void 0) {
1574
2936
  if (!pinOption) {
1575
- throw new ValidationError5(
2937
+ throw new ValidationError6(
1576
2938
  `materializeMany: operand "${name}" holds a segment another operand holds, ${twoPins(prior.at, at)}: one call reads a segment at one generation`
1577
2939
  );
1578
2940
  }
@@ -1600,7 +2962,7 @@ var CloudRoaring = class _CloudRoaring {
1600
2962
  const final = rebindCombineMany(compiled, operandSpecs(pins));
1601
2963
  return runCombineMany(final, {
1602
2964
  source,
1603
- codec: roaringCodec,
2965
+ codec: flagshipCodec(),
1604
2966
  clock: this.clock,
1605
2967
  ...metricsOn ? { metrics: this.metrics } : {}
1606
2968
  });
@@ -1660,7 +3022,7 @@ var CloudRoaring = class _CloudRoaring {
1660
3022
  /** A call's feed with the store's erasure counter: read once here, checked by the combine before any record is read. */
1661
3023
  feedOf(feed, mayBeEmpty, epochAt) {
1662
3024
  if (typeof feed !== "object" || feed === null || Array.isArray(feed)) {
1663
- throw new ValidationError5(
3025
+ throw new ValidationError6(
1664
3026
  "materializeMany: feed must be an object with names, records and counts"
1665
3027
  );
1666
3028
  }
@@ -2103,9 +3465,10 @@ var CloudRoaring = class _CloudRoaring {
2103
3465
  * `input` is ids (any sync or async iterable of integers in `[0, 2^32)`), or a whole bitmap: `{ bitmap }`, anything
2104
3466
  * with `serialize('portable')` such as `roaring`'s `RoaringBitmap32`, or `{ serialized }`, portable Roaring bytes.
2105
3467
  * A bitmap is checked (size cap, structure, safe deserializer) before the first request, written from its own
2106
- * containers with no per-id work, and gives the generation chunk for chunk what its ids would. A bare
2107
- * `RoaringBitmap32`, or a bitmap `deserializePortable` returned, passed as ids loads as `{ bitmap }`. A
2108
- * `Uint8Array` or `Buffer` passed as ids is refused with `ValidationError`, since each byte would load as an id:
3468
+ * containers with no per-id work, and gives the generation chunk for chunk what its ids would. An
3469
+ * iterable with a `serialize` method (a `RoaringBitmap32`, another copy's bitmap, or a bitmap `deserializePortable`
3470
+ * returned) passed as ids loads as `{ bitmap }` and is not iterated. A `Uint8Array` or `Buffer` passed as ids is
3471
+ * refused with `ValidationError`, since each byte would load as an id, even when it has a `serialize` of its own:
2109
3472
  * pass bytes as `{ serialized }`.
2110
3473
  *
2111
3474
  * Ids are held whole in memory before the object is written: the generation's bitmaps and a buffer of up to about 28
@@ -2207,7 +3570,7 @@ var CloudRoaring = class _CloudRoaring {
2207
3570
  const sameBackend = reads !== void 0 && (reads.origin === this.origin || this.registry !== void 0 && REGISTRY_OF.get(reads.origin) === this.registry);
2208
3571
  if (sameBackend && reads.keys.includes(segmentKey(ref))) {
2209
3572
  const named = ref.namespace === void 0 ? ref.segment : `${ref.namespace}/${ref.segment}`;
2210
- throw new ValidationError5(
3573
+ throw new ValidationError6(
2211
3574
  `load: the ids come from a read of the segment "${named}" that is being loaded, and a load publishes over whatever the segment is by then, so another process's newer load of it can be replaced by a result built from the one before, with no conflict reported. This release has no fenced in-place update: write the result into a new segment and point readers at it`
2212
3575
  );
2213
3576
  }
@@ -2271,7 +3634,7 @@ var CloudRoaring = class _CloudRoaring {
2271
3634
  async dropSegment(ref, options) {
2272
3635
  ref = validateRef(ref, "dropSegment");
2273
3636
  if (options === void 0 || options === null) {
2274
- throw new ValidationError5("dropSegment: options { confirmSegment } are required");
3637
+ throw new ValidationError6("dropSegment: options { confirmSegment } are required");
2275
3638
  }
2276
3639
  checkOptions(options, "dropSegment", CALL_KEYS.dropSegment, ["dryRun"]);
2277
3640
  const deps = this.lifecycleDeps("dropSegment");
@@ -2560,7 +3923,7 @@ var CloudRoaring = class _CloudRoaring {
2560
3923
  return new SegmentEngine({
2561
3924
  storage: this.retryOptions === void 0 ? pinned : new RetryingStorageChunkSource2(pinned, this.retryOptions),
2562
3925
  cache: this.cache,
2563
- codec: roaringCodec,
3926
+ codec: flagshipCodec(),
2564
3927
  clock: this.clock,
2565
3928
  metrics: this.metrics,
2566
3929
  budget: this.budget,
@@ -2590,7 +3953,7 @@ var CloudRoaring = class _CloudRoaring {
2590
3953
  if (held.has(key)) {
2591
3954
  const before = held.get(key);
2592
3955
  if (!samePin(before, at)) {
2593
- throw new ValidationError5(
3956
+ throw new ValidationError6(
2594
3957
  `the same segment is in this combine twice, ${twoPins(before, at)}: one call reads a segment at one generation, so materialise one of them into a segment of its own first, with \`materializeMany({ operands: { src: seg }, outputs: [{ dest, expr: { or: ['src'] } }], keep })\``
2595
3958
  );
2596
3959
  }
@@ -2724,7 +4087,7 @@ var CloudRoaring = class _CloudRoaring {
2724
4087
  checkOptions(options, "exportSegments", CALL_KEYS.exportSegments, [], MISPLACED.exportSegments);
2725
4088
  const opts = picked(options, CALL_KEYS.exportSegments);
2726
4089
  const registry = this.requireRegistry("exportSegments");
2727
- return runExport(this, registry, sink, { ...opts, codec: roaringCodec });
4090
+ return runExport(this, registry, sink, { ...opts, codec: flagshipCodec() });
2728
4091
  }
2729
4092
  };
2730
4093
  var withBatches = (gen, batches) => Object.assign(gen, { batches });
@@ -2752,7 +4115,7 @@ var readOptions = (options) => ({
2752
4115
  });
2753
4116
  var NO_SEGMENTS = [];
2754
4117
  function segmentList(list, what) {
2755
- if (!Array.isArray(list)) throw new ValidationError5(`${what} must be an array of segments`);
4118
+ if (!Array.isArray(list)) throw new ValidationError6(`${what} must be an array of segments`);
2756
4119
  return list;
2757
4120
  }
2758
4121
  var STREAM_SOURCES = /* @__PURE__ */ new WeakMap();
@@ -2765,7 +4128,7 @@ function operandsLabel(verb) {
2765
4128
  return verb === "andNot" ? "andNot: `excludes`" : `${verb}: \`others\``;
2766
4129
  }
2767
4130
  function refuseNoOperands(verb) {
2768
- throw new ValidationError5(
4131
+ throw new ValidationError6(
2769
4132
  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 })"
2770
4133
  );
2771
4134
  }
@@ -2846,7 +4209,7 @@ var Segment = class _Segment {
2846
4209
  */
2847
4210
  constructor(parts) {
2848
4211
  if (!minting) {
2849
- throw new ValidationError5(
4212
+ throw new ValidationError6(
2850
4213
  "a Segment is not constructed directly; call `store.segment(name)`"
2851
4214
  );
2852
4215
  }
@@ -2960,11 +4323,11 @@ var Segment = class _Segment {
2960
4323
  leaseUntilOf(op, options) {
2961
4324
  if (options === void 0 || options === null) return void 0;
2962
4325
  if (typeof options !== "object" || Array.isArray(options)) {
2963
- throw new ValidationError5(`${op}: options must be an object such as { leaseUntil }`);
4326
+ throw new ValidationError6(`${op}: options must be an object such as { leaseUntil }`);
2964
4327
  }
2965
4328
  const unknown = Object.keys(options).filter((k) => k !== "leaseUntil");
2966
4329
  if (unknown.length > 0) {
2967
- throw new ValidationError5(
4330
+ throw new ValidationError6(
2968
4331
  `${op}: unknown option${unknown.length > 1 ? "s" : ""} ${unknown.map((k) => `"${k}"`).join(", ")}; this version takes { leaseUntil } only`
2969
4332
  );
2970
4333
  }
@@ -2972,17 +4335,17 @@ var Segment = class _Segment {
2972
4335
  if (until === void 0) return void 0;
2973
4336
  const now = this.clock.now();
2974
4337
  if (typeof until !== "number" || !Number.isSafeInteger(until)) {
2975
- throw new ValidationError5(
4338
+ throw new ValidationError6(
2976
4339
  `${op}: leaseUntil must be an integer epoch-MILLISECONDS; got ${String(until)}`
2977
4340
  );
2978
4341
  }
2979
4342
  if (until <= now) {
2980
- throw new ValidationError5(
4343
+ throw new ValidationError6(
2981
4344
  `${op}: leaseUntil (${until}) is not after now (${now}); it is epoch MILLISECONDS, so a value in seconds reads as long past. Use \`Date.now() + hours * 3_600_000\``
2982
4345
  );
2983
4346
  }
2984
4347
  if (until > now + MAX_LEASE_MS) {
2985
- throw new ValidationError5(
4348
+ throw new ValidationError6(
2986
4349
  `${op}: leaseUntil is more than 14 days away; the longest lease is ${MAX_LEASE_MS} ms. Take a new lease when a job outlasts it`
2987
4350
  );
2988
4351
  }
@@ -3086,22 +4449,22 @@ var Segment = class _Segment {
3086
4449
  const { generation, fingerprint, version } = at ?? {};
3087
4450
  const unknown = typeof at === "object" && at !== null ? Object.keys(at).filter((k) => !["generation", "fingerprint", "version"].includes(k)) : [];
3088
4451
  if (unknown.length > 0) {
3089
- throw new ValidationError5(
4452
+ throw new ValidationError6(
3090
4453
  `pinAt: unknown option${unknown.length > 1 ? "s" : ""} ${unknown.map((k) => `"${k}"`).join(", ")}; pinAt takes { generation, fingerprint } and a pin's \`version\`, which it does not read`
3091
4454
  );
3092
4455
  }
3093
4456
  if (generation === null) {
3094
- throw new ValidationError5(
4457
+ throw new ValidationError6(
3095
4458
  "pinAt: the pin named no generation (the segment had none when it was pinned), so there is nothing to reopen"
3096
4459
  );
3097
4460
  }
3098
4461
  if (version !== void 0 && typeof version !== "string") {
3099
- throw new ValidationError5(
4462
+ throw new ValidationError6(
3100
4463
  "pinAt: `version`, when given, is the string a pin recorded in its pinnedAt; pinAt does not read it, so leave it out if you have none"
3101
4464
  );
3102
4465
  }
3103
4466
  if (typeof generation !== "number" || !Number.isSafeInteger(generation) || generation < 0 || typeof fingerprint !== "string" || !/^\d+:\d+$/.test(fingerprint)) {
3104
- throw new ValidationError5(
4467
+ throw new ValidationError6(
3105
4468
  "pinAt: pass { generation, fingerprint } as recorded by an earlier pin (its pinnedAt); a generation number without the fingerprint of its object does not identify it"
3106
4469
  );
3107
4470
  }
@@ -3150,7 +4513,7 @@ var Segment = class _Segment {
3150
4513
  if (role === void 0) return;
3151
4514
  const { namespace, segment } = dest.ref;
3152
4515
  const named = namespace === void 0 ? segment : `${namespace}/${segment}`;
3153
- throw new ValidationError5(
4516
+ throw new ValidationError6(
3154
4517
  `${verb}: the destination "${named}" is also ${role} of the call, and a call that reads a segment while it publishes to it can replace a newer load of it with a result built from an older one, with no conflict reported. This release has no fenced in-place update: combine into a new segment and point readers at it`
3155
4518
  );
3156
4519
  }
@@ -3580,25 +4943,25 @@ function parseConfig(env) {
3580
4943
  );
3581
4944
  if (unknown.length > 0) {
3582
4945
  const which = unknown.length > 1 ? `${unknown.join(", ")} are not settings export-segments takes.` : `${unknown[0]} is not a setting export-segments takes.`;
3583
- throw new ValidationError6(
4946
+ throw new ValidationError7(
3584
4947
  `${which} It takes ${EXPORT_VARIABLES.join(", ")}; run export-segments --help`
3585
4948
  );
3586
4949
  }
3587
4950
  const root = env.CR_EXPORT_ROOT;
3588
4951
  if (root === void 0 || root === "") {
3589
- throw new ValidationError6(
4952
+ throw new ValidationError7(
3590
4953
  "CR_EXPORT_ROOT is not set: the directory that holds the store's storage/ and registry/. export-segments also needs CR_EXPORT_OUT; run export-segments --help"
3591
4954
  );
3592
4955
  }
3593
4956
  const out = env.CR_EXPORT_OUT;
3594
4957
  if (out === void 0 || out === "") {
3595
- throw new ValidationError6(
4958
+ throw new ValidationError7(
3596
4959
  "CR_EXPORT_OUT is not set: the directory to write the dump to. export-segments also needs CR_EXPORT_ROOT; run export-segments --help"
3597
4960
  );
3598
4961
  }
3599
4962
  const format = env.CR_EXPORT_FORMAT || "roaring";
3600
4963
  if (format !== "roaring" && format !== "ndjson") {
3601
- throw new ValidationError6(`CR_EXPORT_FORMAT must be "roaring" or "ndjson"; got ${format}`);
4964
+ throw new ValidationError7(`CR_EXPORT_FORMAT must be "roaring" or "ndjson"; got ${format}`);
3602
4965
  }
3603
4966
  const namespace = env.CR_EXPORT_NAMESPACE || void 0;
3604
4967
  return { root, out, format, namespace };
@@ -3613,7 +4976,7 @@ async function ensureOwnDirectory(out, dir) {
3613
4976
  }
3614
4977
  const found = await lstat(dir);
3615
4978
  const refuse = (why) => {
3616
- throw new ValidationError6(`the export directory is not one this tool made: ${why}`);
4979
+ throw new ValidationError7(`the export directory is not one this tool made: ${why}`);
3617
4980
  };
3618
4981
  if (found.isSymbolicLink()) refuse("a namespace directory is a symbolic link");
3619
4982
  if (!found.isDirectory()) refuse("a namespace path is not a directory");
@@ -3628,7 +4991,7 @@ function fsSink(out) {
3628
4991
  async open(ref, ext) {
3629
4992
  const part = namespacePathPart(ref.namespace);
3630
4993
  if (part.toLowerCase() === MANIFEST_NAME) {
3631
- throw new ValidationError6(
4994
+ throw new ValidationError7(
3632
4995
  `a namespace named ${MANIFEST_NAME} (in any letter case) cannot be exported to a directory: its folder would be the manifest's path`
3633
4996
  );
3634
4997
  }
@@ -3673,10 +5036,10 @@ async function requireStoreRoot(root) {
3673
5036
  try {
3674
5037
  entries = await readdir(root);
3675
5038
  } catch {
3676
- throw new ValidationError6("CR_EXPORT_ROOT does not name a directory that can be read");
5039
+ throw new ValidationError7("CR_EXPORT_ROOT does not name a directory that can be read");
3677
5040
  }
3678
5041
  if (entries.length === 0) {
3679
- throw new ValidationError6(
5042
+ throw new ValidationError7(
3680
5043
  "CR_EXPORT_ROOT is empty: it holds no store (an unmounted volume, or the wrong directory)"
3681
5044
  );
3682
5045
  }
@@ -3692,7 +5055,7 @@ async function main(env = process.env, now = () => Date.now()) {
3692
5055
  const store = new CloudRoaring({ storage });
3693
5056
  const priorManifest = await lstat(join(config.out, MANIFEST_NAME)).catch(() => null);
3694
5057
  if (priorManifest?.isDirectory() === true) {
3695
- throw new ValidationError6(
5058
+ throw new ValidationError7(
3696
5059
  `${join(config.out, MANIFEST_NAME)} is a directory, so the manifest cannot be written there: remove or rename it, or export to a fresh directory`
3697
5060
  );
3698
5061
  }