@cloudbitmaps/roaring 0.25.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -2128,6 +2128,59 @@ export declare class Segment {
2128
2128
  * {@link ValidationError} before any request.
2129
2129
  */
2130
2130
  andNotInto(dest: Segment, excludes: Segment[], options?: CombineOptions): Promise<MaterializeResult>;
2131
+ /**
2132
+ * How many ids `this ∩ others…` holds (minus `exclude`): the length of what {@link intersect} streams, without
2133
+ * streaming it. Every key all the operands hold is decoded and counted as the stream reads it, and a key only some
2134
+ * operands hold is not read, so the call makes the requests {@link intersect} makes and returns a number instead of
2135
+ * the ids. It is exact: it never answers a key from an index, so it trusts nothing {@link count} trusts.
2136
+ *
2137
+ * The range, `concurrency`, `budget`, `allowAbsentOperands` and `exclude` are {@link intersect}'s; a write option fails
2138
+ * the call with {@link ValidationError} before any request, and so does an empty `others` (to count one segment, use
2139
+ * {@link count}).
2140
+ *
2141
+ * Like a stream, a count that runs while a segment is erased or reloaded can describe two instants, within the bound
2142
+ * the streams state. A union or a difference, and an intersection with an `exclude`, looks at its operands'
2143
+ * generations every `concurrency` keys; an intersection with no `exclude` makes no such look, since it decodes every
2144
+ * key and so shows a move in the chunks it decodes, as its stream does. Either way it plans again above the last key
2145
+ * it took when one moved. A pinned handle counts the generation it pinned, and each pinned operand's object is
2146
+ * looked up once before the first key (one footer read each, which `budget` does not charge, and which the stream
2147
+ * does not make), and again at each look where there is one, so an erasure of what it pinned fails the count with
2148
+ * {@link NotFoundError}; a
2149
+ * fault the look meets other than a transient one, which is retried, is raised as it is. A call that involves a
2150
+ * handle whose lease has ended, or has ended by the next look, throws {@link LeaseExpiredError}.
2151
+ */
2152
+ intersectCount(others: Segment[], options?: CombineOptions): Promise<number>;
2153
+ /**
2154
+ * How many ids `this ∪ others…` holds (minus `exclude`): the length of what {@link union} streams, without streaming
2155
+ * it. A chunk key only one operand holds, that no `exclude` holds and the range does not cut, is answered from that
2156
+ * operand's index, so a union of segments that mostly do not overlap reads little of them; every other key is
2157
+ * decoded and counted. On handles that are not pinned it makes no more requests than {@link union} does, and reads
2158
+ * fewer bytes when the shared keys are few. An empty `others`, with no `exclude` and no range, is {@link count} of
2159
+ * `this`, answered from the registry row when it can be; when that figure is 0 it adds one registry read, to refuse
2160
+ * a segment that does not exist as the stream does.
2161
+ *
2162
+ * What it trusts: the index, for each key it answers without decoding, as {@link count} does, so a party who can write
2163
+ * an object's index can make that key's figure wrong; a decoded key is exact. A source with no per-chunk counts
2164
+ * decodes every key. It takes the options {@link intersectCount} takes; the erasure bound, the lease checks and the
2165
+ * pinned handles are as for {@link intersectCount}, a pinned operand adding a footer read before the first key and at
2166
+ * each look. An empty `others` on a pinned handle is {@link count} of the pin, with no look.
2167
+ */
2168
+ unionCount(others: Segment[], options?: CombineOptions): Promise<number>;
2169
+ /**
2170
+ * How many ids `this \ (excludes…)` holds: the length of what {@link andNot} streams, without streaming it. A chunk
2171
+ * key of `this` that no exclude holds and the range does not cut is answered from its index and not read; a key an
2172
+ * exclude shares is decoded and counted. On handles that are not pinned it makes no more requests than {@link andNot}
2173
+ * does, and reads fewer bytes when the excludes overlap little of `this`. An empty `excludes`, with no range, is
2174
+ * {@link count} of `this` (the stream of it is the whole of `this`), answered from the registry row when it can be,
2175
+ * with one registry read added when that figure is 0.
2176
+ *
2177
+ * It takes the options {@link andNot} takes (every one of {@link intersectCount}'s but `exclude`, which a count of a
2178
+ * difference has no use for, since `excludes` is its subtraction) and trusts what {@link unionCount} trusts. The
2179
+ * erasure bound, the lease checks and the pinned handles are as for {@link intersectCount}.
2180
+ */
2181
+ andNotCount(excludes: Segment[], options?: CombineOptions): Promise<number>;
2182
+ /** The one body of the three count methods, after each has checked its own options. */
2183
+ private countCombine;
2131
2184
  /**
2132
2185
  * The one body of the three combines, read as ids or as chunks. `operands` is `others` for `intersect` and
2133
2186
  * `union`, and `excludes` for `andNot`, which takes no `exclude` option.
package/dist/index.js CHANGED
@@ -3973,6 +3973,29 @@ var CALL_KEYS = {
3973
3973
  "allowAbsentOperands",
3974
3974
  "exclude"
3975
3975
  ]),
3976
+ intersectCount: keysOf()([
3977
+ "after",
3978
+ "through",
3979
+ "concurrency",
3980
+ "budget",
3981
+ "allowAbsentOperands",
3982
+ "exclude"
3983
+ ]),
3984
+ unionCount: keysOf()([
3985
+ "after",
3986
+ "through",
3987
+ "concurrency",
3988
+ "budget",
3989
+ "allowAbsentOperands",
3990
+ "exclude"
3991
+ ]),
3992
+ andNotCount: keysOf()([
3993
+ "after",
3994
+ "through",
3995
+ "concurrency",
3996
+ "budget",
3997
+ "allowAbsentOperands"
3998
+ ]),
3976
3999
  into: keysOf()([
3977
4000
  "after",
3978
4001
  "through",
@@ -4050,6 +4073,9 @@ var MISPLACED = {
4050
4073
  range: outside(CALL_KEYS.into, CALL_KEYS.range),
4051
4074
  andNot: outside(CALL_KEYS.into, CALL_KEYS.andNot),
4052
4075
  combine: outside(CALL_KEYS.into, CALL_KEYS.combine),
4076
+ intersectCount: outside(CALL_KEYS.into, CALL_KEYS.intersectCount),
4077
+ unionCount: outside(CALL_KEYS.into, CALL_KEYS.unionCount),
4078
+ andNotCount: outside(CALL_KEYS.into, CALL_KEYS.andNotCount),
4053
4079
  andNotInto: outside(CALL_KEYS.into, CALL_KEYS.andNotInto),
4054
4080
  exportSegments: ["codec"]
4055
4081
  };
@@ -5816,7 +5842,7 @@ function operandsLabel(verb) {
5816
5842
  }
5817
5843
  function refuseNoOperands(verb) {
5818
5844
  throw new ValidationError6(
5819
- verb === "intersect" ? "intersect requires at least one segment to intersect with; to read every id of one segment, use iterate()" : "intersectInto requires at least one segment to intersect with; to copy this segment into dest, call materializeMany({ operands: { src: thisSegment }, outputs: [{ dest, expr: { or: ['src'] } }], keep })"
5845
+ verb === "intersect" ? "intersect requires at least one segment to intersect with; to read every id of one segment, use iterate()" : verb === "intersectCount" ? "intersectCount requires at least one segment to intersect with; to count one segment, use count()" : "intersectInto requires at least one segment to intersect with; to copy this segment into dest, call materializeMany({ operands: { src: thisSegment }, outputs: [{ dest, expr: { or: ['src'] } }], keep })"
5820
5846
  );
5821
5847
  }
5822
5848
  var AS_IDS = {
@@ -6526,6 +6552,111 @@ var Segment = class _Segment {
6526
6552
  );
6527
6553
  return this.combineInto("andNotInto", dest, excludes, options);
6528
6554
  }
6555
+ /**
6556
+ * How many ids `this ∩ others…` holds (minus `exclude`): the length of what {@link intersect} streams, without
6557
+ * streaming it. Every key all the operands hold is decoded and counted as the stream reads it, and a key only some
6558
+ * operands hold is not read, so the call makes the requests {@link intersect} makes and returns a number instead of
6559
+ * the ids. It is exact: it never answers a key from an index, so it trusts nothing {@link count} trusts.
6560
+ *
6561
+ * The range, `concurrency`, `budget`, `allowAbsentOperands` and `exclude` are {@link intersect}'s; a write option fails
6562
+ * the call with {@link ValidationError} before any request, and so does an empty `others` (to count one segment, use
6563
+ * {@link count}).
6564
+ *
6565
+ * Like a stream, a count that runs while a segment is erased or reloaded can describe two instants, within the bound
6566
+ * the streams state. A union or a difference, and an intersection with an `exclude`, looks at its operands'
6567
+ * generations every `concurrency` keys; an intersection with no `exclude` makes no such look, since it decodes every
6568
+ * key and so shows a move in the chunks it decodes, as its stream does. Either way it plans again above the last key
6569
+ * it took when one moved. A pinned handle counts the generation it pinned, and each pinned operand's object is
6570
+ * looked up once before the first key (one footer read each, which `budget` does not charge, and which the stream
6571
+ * does not make), and again at each look where there is one, so an erasure of what it pinned fails the count with
6572
+ * {@link NotFoundError}; a
6573
+ * fault the look meets other than a transient one, which is retried, is raised as it is. A call that involves a
6574
+ * handle whose lease has ended, or has ended by the next look, throws {@link LeaseExpiredError}.
6575
+ */
6576
+ async intersectCount(others, options) {
6577
+ checkOptions(
6578
+ options,
6579
+ "intersectCount",
6580
+ CALL_KEYS.intersectCount,
6581
+ ["allowAbsentOperands"],
6582
+ MISPLACED.intersectCount
6583
+ );
6584
+ return this.countCombine("intersect", others, options ?? void 0);
6585
+ }
6586
+ /**
6587
+ * How many ids `this ∪ others…` holds (minus `exclude`): the length of what {@link union} streams, without streaming
6588
+ * it. A chunk key only one operand holds, that no `exclude` holds and the range does not cut, is answered from that
6589
+ * operand's index, so a union of segments that mostly do not overlap reads little of them; every other key is
6590
+ * decoded and counted. On handles that are not pinned it makes no more requests than {@link union} does, and reads
6591
+ * fewer bytes when the shared keys are few. An empty `others`, with no `exclude` and no range, is {@link count} of
6592
+ * `this`, answered from the registry row when it can be; when that figure is 0 it adds one registry read, to refuse
6593
+ * a segment that does not exist as the stream does.
6594
+ *
6595
+ * What it trusts: the index, for each key it answers without decoding, as {@link count} does, so a party who can write
6596
+ * an object's index can make that key's figure wrong; a decoded key is exact. A source with no per-chunk counts
6597
+ * decodes every key. It takes the options {@link intersectCount} takes; the erasure bound, the lease checks and the
6598
+ * pinned handles are as for {@link intersectCount}, a pinned operand adding a footer read before the first key and at
6599
+ * each look. An empty `others` on a pinned handle is {@link count} of the pin, with no look.
6600
+ */
6601
+ async unionCount(others, options) {
6602
+ checkOptions(
6603
+ options,
6604
+ "unionCount",
6605
+ CALL_KEYS.unionCount,
6606
+ ["allowAbsentOperands"],
6607
+ MISPLACED.unionCount
6608
+ );
6609
+ return this.countCombine("union", others, options ?? void 0);
6610
+ }
6611
+ /**
6612
+ * How many ids `this \ (excludes…)` holds: the length of what {@link andNot} streams, without streaming it. A chunk
6613
+ * key of `this` that no exclude holds and the range does not cut is answered from its index and not read; a key an
6614
+ * exclude shares is decoded and counted. On handles that are not pinned it makes no more requests than {@link andNot}
6615
+ * does, and reads fewer bytes when the excludes overlap little of `this`. An empty `excludes`, with no range, is
6616
+ * {@link count} of `this` (the stream of it is the whole of `this`), answered from the registry row when it can be,
6617
+ * with one registry read added when that figure is 0.
6618
+ *
6619
+ * It takes the options {@link andNot} takes (every one of {@link intersectCount}'s but `exclude`, which a count of a
6620
+ * difference has no use for, since `excludes` is its subtraction) and trusts what {@link unionCount} trusts. The
6621
+ * erasure bound, the lease checks and the pinned handles are as for {@link intersectCount}.
6622
+ */
6623
+ async andNotCount(excludes, options) {
6624
+ checkOptions(
6625
+ options,
6626
+ "andNotCount",
6627
+ CALL_KEYS.andNotCount,
6628
+ ["allowAbsentOperands"],
6629
+ MISPLACED.andNotCount
6630
+ );
6631
+ return this.countCombine("andNot", excludes, options ?? void 0);
6632
+ }
6633
+ /** The one body of the three count methods, after each has checked its own options. */
6634
+ async countCombine(verb, operands, options) {
6635
+ const name = `${verb}Count`;
6636
+ const exclude = verb === "andNot" ? NO_SEGMENTS : this.excludesOf(options);
6637
+ const others = segmentList(
6638
+ operands,
6639
+ verb === "andNot" ? `${name}: \`excludes\`` : `${name}: \`others\``
6640
+ );
6641
+ if (verb === "intersect" && others.length === 0) refuseNoOperands("intersectCount");
6642
+ const handles = [this, ...others, ...exclude];
6643
+ this.assertSegments(name, verb === "andNot" ? "an exclude" : "an operand", others);
6644
+ this.assertSegments(name, "an exclude", exclude);
6645
+ this.assertLeases(handles);
6646
+ const engine = this.combineEngine(handles) ?? this.engine;
6647
+ const read = options == null ? void 0 : readOptions(options);
6648
+ const guard2 = handles.some((h) => h.leaseHold !== void 0) ? () => this.assertLeases(handles) : void 0;
6649
+ const opts = guard2 === void 0 ? read : { ...read, guard: guard2 };
6650
+ const refs = others.map((o) => o.ref);
6651
+ if (verb === "andNot") return engine.combineCount([this.ref], refs, "all", verb, opts);
6652
+ return engine.combineCount(
6653
+ [this.ref, ...refs],
6654
+ exclude.map((o) => o.ref),
6655
+ verb === "union" ? "any" : "all",
6656
+ verb,
6657
+ opts
6658
+ );
6659
+ }
6529
6660
  /**
6530
6661
  * The one body of the three combines, read as ids or as chunks. `operands` is `others` for `intersect` and
6531
6662
  * `union`, and `excludes` for `andNot`, which takes no `exclude` option.