distillate 0.7.0 → 0.8.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/README.md +22 -19
- package/dist/blocked/index.cjs +11 -112
- package/dist/blocked/index.d.cts +2 -2
- package/dist/blocked/index.d.ts +2 -2
- package/dist/blocked/index.js +6 -113
- package/dist/bloom/index.cjs +8 -97
- package/dist/bloom/index.d.cts +2 -2
- package/dist/bloom/index.d.ts +2 -2
- package/dist/bloom/index.js +3 -98
- package/dist/fuse/index.cjs +10 -111
- package/dist/fuse/index.d.cts +2 -2
- package/dist/fuse/index.d.ts +2 -2
- package/dist/fuse/index.js +5 -112
- package/dist/index.cjs +1 -2
- package/dist/index.js +1 -2
- package/dist/{params-BrWuBC2A.js → params-CeajSrwv.js} +0 -7
- package/dist/{params--8CNXYWu.cjs → params-UTZbJ22c.cjs} +0 -7
- package/dist/{serialize-BnwtzcMw.js → serialize-BqIcsR2J.js} +3 -29
- package/dist/{serialize-BIIKUHH6.cjs → serialize-CXnRWItH.cjs} +26 -28
- package/dist/serialize-ChyWpB9F.d.cts +73 -0
- package/dist/serialize-ChyWpB9F.d.ts +73 -0
- package/package.json +2 -3
- package/dist/serialize-DRKh6QOr.d.cts +0 -15
- package/dist/serialize-DRKh6QOr.d.ts +0 -15
package/dist/bloom/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_serialize = require("../serialize-
|
|
3
|
-
const require_params = require("../params
|
|
2
|
+
const require_serialize = require("../serialize-CXnRWItH.cjs");
|
|
3
|
+
const require_params = require("../params-UTZbJ22c.cjs");
|
|
4
4
|
//#region src/core/bitset.ts
|
|
5
5
|
var BitSetRangeError = class extends RangeError {
|
|
6
6
|
name = "BitSetRangeError";
|
|
@@ -33,7 +33,6 @@ var BitSet = class {
|
|
|
33
33
|
};
|
|
34
34
|
//#endregion
|
|
35
35
|
//#region src/core/sizing.ts
|
|
36
|
-
/** Optimal Bloom-filter sizing: `m` bits and `k` hashes for `n` items at target FPR `epsilon`. */
|
|
37
36
|
function bloomSizing(n, epsilon) {
|
|
38
37
|
const m = Math.ceil(-n * Math.log(epsilon) / (Math.LN2 * Math.LN2));
|
|
39
38
|
return {
|
|
@@ -44,23 +43,9 @@ function bloomSizing(n, epsilon) {
|
|
|
44
43
|
//#endregion
|
|
45
44
|
//#region src/bloom/bloom.ts
|
|
46
45
|
const TYPE = 1;
|
|
47
|
-
/** Thrown when an operation requires two filters built with identical parameters. */
|
|
48
46
|
var BloomParamMismatchError = class extends Error {
|
|
49
|
-
/** Discriminates this error from other `Error`s. */
|
|
50
47
|
name = "BloomParamMismatchError";
|
|
51
48
|
};
|
|
52
|
-
/**
|
|
53
|
-
* A classic Bloom filter: a space-efficient set with a tunable false-positive
|
|
54
|
-
* rate and zero false negatives.
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
* ```ts
|
|
58
|
-
* const filter = BloomFilter.create(100_000, 0.01);
|
|
59
|
-
* filter.add("alice");
|
|
60
|
-
* filter.has("alice"); // true
|
|
61
|
-
* filter.has("bob"); // false (or a ~1% false positive)
|
|
62
|
-
* ```
|
|
63
|
-
*/
|
|
64
49
|
var BloomFilter = class BloomFilter {
|
|
65
50
|
#bits;
|
|
66
51
|
#m;
|
|
@@ -68,40 +53,18 @@ var BloomFilter = class BloomFilter {
|
|
|
68
53
|
#seed;
|
|
69
54
|
#scratch;
|
|
70
55
|
#n;
|
|
71
|
-
/**
|
|
72
|
-
* Creates a filter sized for `n` expected keys at a target false-positive rate.
|
|
73
|
-
*
|
|
74
|
-
* @param n - Expected number of keys.
|
|
75
|
-
* @param epsilon - Target false-positive rate, e.g. `0.01` for 1%.
|
|
76
|
-
* @returns A new, empty filter.
|
|
77
|
-
*/
|
|
78
56
|
static create(n, epsilon) {
|
|
79
57
|
require_params.assertPositiveInt(n, "n");
|
|
80
58
|
require_params.assertUint32(n, "n");
|
|
81
59
|
require_params.assertProbability(epsilon, "epsilon");
|
|
82
60
|
return BloomFilter.#withN(bloomSizing(n, epsilon), n);
|
|
83
61
|
}
|
|
84
|
-
/**
|
|
85
|
-
* Builds a filter from `keys`, sized for their count at the target
|
|
86
|
-
* false-positive rate. The ergonomic entry point when the key set is already
|
|
87
|
-
* in hand; use {@link BloomFilter.create} to size for a count known ahead.
|
|
88
|
-
*
|
|
89
|
-
* @param keys - The keys to insert.
|
|
90
|
-
* @param epsilon - Target false-positive rate, e.g. `0.01` for 1%.
|
|
91
|
-
* @returns A new filter containing every key.
|
|
92
|
-
*/
|
|
93
62
|
static from(keys, epsilon) {
|
|
94
63
|
const arr = [...keys];
|
|
95
64
|
const f = BloomFilter.create(Math.max(1, arr.length), epsilon);
|
|
96
65
|
for (const k of arr) f.add(k);
|
|
97
66
|
return f;
|
|
98
67
|
}
|
|
99
|
-
/**
|
|
100
|
-
* Restores a filter from its {@link BloomFilter.toBytes} serialization.
|
|
101
|
-
*
|
|
102
|
-
* @param bytes - The serialized filter.
|
|
103
|
-
* @returns The reconstructed filter.
|
|
104
|
-
*/
|
|
105
68
|
static fromBytes(bytes) {
|
|
106
69
|
const { type, flags, body } = require_serialize.readHeader(bytes);
|
|
107
70
|
if (type !== TYPE) throw new require_serialize.SerializationError(`expected AMQF type ${String(TYPE)}, got ${String(type)}`);
|
|
@@ -121,10 +84,6 @@ var BloomFilter = class BloomFilter {
|
|
|
121
84
|
f.#bits.bytes.set(body.subarray(14));
|
|
122
85
|
return f;
|
|
123
86
|
}
|
|
124
|
-
/**
|
|
125
|
-
* Constructs a filter from low-level {@link BloomParams}. Prefer
|
|
126
|
-
* {@link BloomFilter.create} unless restoring a specific configuration.
|
|
127
|
-
*/
|
|
128
87
|
constructor({ m, k, seed = 0 }) {
|
|
129
88
|
require_params.assertPositiveInt(m, "m");
|
|
130
89
|
require_params.assertUint32(m, "m");
|
|
@@ -143,41 +102,24 @@ var BloomFilter = class BloomFilter {
|
|
|
143
102
|
f.#n = n;
|
|
144
103
|
return f;
|
|
145
104
|
}
|
|
146
|
-
/** Number of bits in the filter. */
|
|
147
105
|
get m() {
|
|
148
106
|
return this.#m;
|
|
149
107
|
}
|
|
150
|
-
/** Number of hash probes per key. */
|
|
151
108
|
get k() {
|
|
152
109
|
return this.#k;
|
|
153
110
|
}
|
|
154
|
-
/** Hash seed. */
|
|
155
111
|
get seed() {
|
|
156
112
|
return this.#seed;
|
|
157
113
|
}
|
|
158
|
-
/** Number of bits currently set. */
|
|
159
114
|
get length() {
|
|
160
115
|
return this.#bits.count();
|
|
161
116
|
}
|
|
162
|
-
/** Analytic design bits-per-key `m / n`. */
|
|
163
117
|
get bitsPerKey() {
|
|
164
118
|
return this.#m / this.#n;
|
|
165
119
|
}
|
|
166
|
-
/**
|
|
167
|
-
* Estimates the current false-positive rate from the actual fill,
|
|
168
|
-
* `(length / m) ** k`. This reflects how full the filter is right now, not
|
|
169
|
-
* the design target; it rises as keys are added.
|
|
170
|
-
*
|
|
171
|
-
* @returns The estimated false-positive rate, `0` for an empty filter.
|
|
172
|
-
*/
|
|
173
120
|
rate() {
|
|
174
121
|
return (this.length / this.#m) ** this.#k;
|
|
175
122
|
}
|
|
176
|
-
/**
|
|
177
|
-
* Serializes the filter to a portable little-endian byte layout.
|
|
178
|
-
*
|
|
179
|
-
* @returns The serialized filter, readable by {@link BloomFilter.fromBytes}.
|
|
180
|
-
*/
|
|
181
123
|
toBytes() {
|
|
182
124
|
const payload = this.#bits.bytes;
|
|
183
125
|
return require_serialize.writeFrame({
|
|
@@ -192,41 +134,15 @@ var BloomFilter = class BloomFilter {
|
|
|
192
134
|
body.set(payload, 14);
|
|
193
135
|
});
|
|
194
136
|
}
|
|
195
|
-
/**
|
|
196
|
-
* Tests structural equality: `true` when `other` serializes to identical
|
|
197
|
-
* bytes, meaning identical parameters and set bits.
|
|
198
|
-
*
|
|
199
|
-
* @param other - The filter to compare against.
|
|
200
|
-
* @returns `true` if the two filters are byte-for-byte identical.
|
|
201
|
-
*/
|
|
202
137
|
equals(other) {
|
|
203
138
|
return require_serialize.bytesEqual(this.toBytes(), other.toBytes());
|
|
204
139
|
}
|
|
205
|
-
/**
|
|
206
|
-
* Serializes the filter to a JSON-friendly envelope wrapping the base64 of
|
|
207
|
-
* {@link BloomFilter.toBytes}.
|
|
208
|
-
*
|
|
209
|
-
* @returns The envelope, readable by {@link BloomFilter.fromJSON}.
|
|
210
|
-
*/
|
|
211
140
|
toJSON() {
|
|
212
141
|
return require_serialize.toJSONEnvelope(this.toBytes());
|
|
213
142
|
}
|
|
214
|
-
/**
|
|
215
|
-
* Restores a filter from its {@link BloomFilter.toJSON} envelope.
|
|
216
|
-
*
|
|
217
|
-
* @param value - The JSON envelope.
|
|
218
|
-
* @returns The reconstructed filter.
|
|
219
|
-
*/
|
|
220
143
|
static fromJSON(value) {
|
|
221
144
|
return BloomFilter.fromBytes(require_serialize.fromJSONEnvelope(value));
|
|
222
145
|
}
|
|
223
|
-
/**
|
|
224
|
-
* Returns a new filter containing the union of this filter and `other`.
|
|
225
|
-
*
|
|
226
|
-
* @param other - A filter built with identical parameters.
|
|
227
|
-
* @returns A new filter reporting membership for keys in either input.
|
|
228
|
-
* @throws {@link BloomParamMismatchError} if the parameters differ.
|
|
229
|
-
*/
|
|
230
146
|
union(other) {
|
|
231
147
|
if (this.#m !== other.#m || this.#k !== other.#k || this.#seed !== other.#seed) throw new BloomParamMismatchError("cannot union Bloom filters whose parameters do not match");
|
|
232
148
|
const a = this.#bits.bytes;
|
|
@@ -241,21 +157,10 @@ var BloomFilter = class BloomFilter {
|
|
|
241
157
|
r.#bits.bytes.set(merged);
|
|
242
158
|
return r;
|
|
243
159
|
}
|
|
244
|
-
/**
|
|
245
|
-
* Adds a key to the set.
|
|
246
|
-
*
|
|
247
|
-
* @param key - The key to insert, as a string or bytes.
|
|
248
|
-
*/
|
|
249
160
|
add(key) {
|
|
250
161
|
require_serialize.probeInto(key, this.#k, this.#m, this.#seed, this.#scratch);
|
|
251
162
|
for (let i = 0; i < this.#k; i++) this.#bits.set(this.#scratch[i] ?? 0);
|
|
252
163
|
}
|
|
253
|
-
/**
|
|
254
|
-
* Tests whether a key is in the set.
|
|
255
|
-
*
|
|
256
|
-
* @param key - The key to test.
|
|
257
|
-
* @returns `true` if present (possibly a false positive); `false` guarantees absence.
|
|
258
|
-
*/
|
|
259
164
|
has(key) {
|
|
260
165
|
require_serialize.probeInto(key, this.#k, this.#m, this.#seed, this.#scratch);
|
|
261
166
|
for (let i = 0; i < this.#k; i++) if (!this.#bits.get(this.#scratch[i] ?? 0)) return false;
|
|
@@ -263,7 +168,13 @@ var BloomFilter = class BloomFilter {
|
|
|
263
168
|
}
|
|
264
169
|
};
|
|
265
170
|
//#endregion
|
|
171
|
+
exports.BadMagicError = require_serialize.BadMagicError;
|
|
266
172
|
exports.BloomFilter = BloomFilter;
|
|
267
173
|
exports.BloomParamMismatchError = BloomParamMismatchError;
|
|
174
|
+
exports.ChecksumError = require_serialize.ChecksumError;
|
|
268
175
|
exports.ParamError = require_params.ParamError;
|
|
176
|
+
exports.SerializationError = require_serialize.SerializationError;
|
|
177
|
+
exports.TruncatedError = require_serialize.TruncatedError;
|
|
178
|
+
exports.UnknownHashVariantError = require_serialize.UnknownHashVariantError;
|
|
179
|
+
exports.UnknownVersionError = require_serialize.UnknownVersionError;
|
|
269
180
|
exports.bloomSizing = bloomSizing;
|
package/dist/bloom/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as TruncatedError, c as BytesLike, i as SerializationError, n as ChecksumError, o as UnknownHashVariantError, r as FilterJSON, s as UnknownVersionError, t as BadMagicError } from "../serialize-ChyWpB9F.cjs";
|
|
2
2
|
import { t as ParamError } from "../params-DnqJBqLS.cjs";
|
|
3
3
|
//#region src/bloom/bloom.d.ts
|
|
4
4
|
/** Thrown when an operation requires two filters built with identical parameters. */
|
|
@@ -139,4 +139,4 @@ interface BloomSizing {
|
|
|
139
139
|
/** Optimal Bloom-filter sizing: `m` bits and `k` hashes for `n` items at target FPR `epsilon`. */
|
|
140
140
|
declare function bloomSizing(n: number, epsilon: number): BloomSizing;
|
|
141
141
|
//#endregion
|
|
142
|
-
export { BloomFilter, BloomParamMismatchError, type BloomParams, type BloomSizing, type FilterJSON, ParamError, bloomSizing };
|
|
142
|
+
export { BadMagicError, BloomFilter, BloomParamMismatchError, type BloomParams, type BloomSizing, ChecksumError, type FilterJSON, ParamError, SerializationError, TruncatedError, UnknownHashVariantError, UnknownVersionError, bloomSizing };
|
package/dist/bloom/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as TruncatedError, c as BytesLike, i as SerializationError, n as ChecksumError, o as UnknownHashVariantError, r as FilterJSON, s as UnknownVersionError, t as BadMagicError } from "../serialize-ChyWpB9F.js";
|
|
2
2
|
import { t as ParamError } from "../params-DnqJBqLS.js";
|
|
3
3
|
//#region src/bloom/bloom.d.ts
|
|
4
4
|
/** Thrown when an operation requires two filters built with identical parameters. */
|
|
@@ -139,4 +139,4 @@ interface BloomSizing {
|
|
|
139
139
|
/** Optimal Bloom-filter sizing: `m` bits and `k` hashes for `n` items at target FPR `epsilon`. */
|
|
140
140
|
declare function bloomSizing(n: number, epsilon: number): BloomSizing;
|
|
141
141
|
//#endregion
|
|
142
|
-
export { BloomFilter, BloomParamMismatchError, type BloomParams, type BloomSizing, type FilterJSON, ParamError, bloomSizing };
|
|
142
|
+
export { BadMagicError, BloomFilter, BloomParamMismatchError, type BloomParams, type BloomSizing, ChecksumError, type FilterJSON, ParamError, SerializationError, TruncatedError, UnknownHashVariantError, UnknownVersionError, bloomSizing };
|
package/dist/bloom/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { a as assertUint16, i as assertProbability, o as assertUint32, r as assertPositiveInt, t as ParamError } from "../params-
|
|
1
|
+
import { a as UnknownHashVariantError, b as probeInto, c as assertMinBodyLength, d as readHeader, f as toJSONEnvelope, i as TruncatedError, l as bytesEqual, n as ChecksumError, o as UnknownVersionError, p as writeFrame, r as SerializationError, s as assertBodyLength, t as BadMagicError, u as fromJSONEnvelope } from "../serialize-BqIcsR2J.js";
|
|
2
|
+
import { a as assertUint16, i as assertProbability, o as assertUint32, r as assertPositiveInt, t as ParamError } from "../params-CeajSrwv.js";
|
|
3
3
|
//#region src/core/bitset.ts
|
|
4
4
|
var BitSetRangeError = class extends RangeError {
|
|
5
5
|
name = "BitSetRangeError";
|
|
@@ -32,7 +32,6 @@ var BitSet = class {
|
|
|
32
32
|
};
|
|
33
33
|
//#endregion
|
|
34
34
|
//#region src/core/sizing.ts
|
|
35
|
-
/** Optimal Bloom-filter sizing: `m` bits and `k` hashes for `n` items at target FPR `epsilon`. */
|
|
36
35
|
function bloomSizing(n, epsilon) {
|
|
37
36
|
const m = Math.ceil(-n * Math.log(epsilon) / (Math.LN2 * Math.LN2));
|
|
38
37
|
return {
|
|
@@ -43,23 +42,9 @@ function bloomSizing(n, epsilon) {
|
|
|
43
42
|
//#endregion
|
|
44
43
|
//#region src/bloom/bloom.ts
|
|
45
44
|
const TYPE = 1;
|
|
46
|
-
/** Thrown when an operation requires two filters built with identical parameters. */
|
|
47
45
|
var BloomParamMismatchError = class extends Error {
|
|
48
|
-
/** Discriminates this error from other `Error`s. */
|
|
49
46
|
name = "BloomParamMismatchError";
|
|
50
47
|
};
|
|
51
|
-
/**
|
|
52
|
-
* A classic Bloom filter: a space-efficient set with a tunable false-positive
|
|
53
|
-
* rate and zero false negatives.
|
|
54
|
-
*
|
|
55
|
-
* @example
|
|
56
|
-
* ```ts
|
|
57
|
-
* const filter = BloomFilter.create(100_000, 0.01);
|
|
58
|
-
* filter.add("alice");
|
|
59
|
-
* filter.has("alice"); // true
|
|
60
|
-
* filter.has("bob"); // false (or a ~1% false positive)
|
|
61
|
-
* ```
|
|
62
|
-
*/
|
|
63
48
|
var BloomFilter = class BloomFilter {
|
|
64
49
|
#bits;
|
|
65
50
|
#m;
|
|
@@ -67,40 +52,18 @@ var BloomFilter = class BloomFilter {
|
|
|
67
52
|
#seed;
|
|
68
53
|
#scratch;
|
|
69
54
|
#n;
|
|
70
|
-
/**
|
|
71
|
-
* Creates a filter sized for `n` expected keys at a target false-positive rate.
|
|
72
|
-
*
|
|
73
|
-
* @param n - Expected number of keys.
|
|
74
|
-
* @param epsilon - Target false-positive rate, e.g. `0.01` for 1%.
|
|
75
|
-
* @returns A new, empty filter.
|
|
76
|
-
*/
|
|
77
55
|
static create(n, epsilon) {
|
|
78
56
|
assertPositiveInt(n, "n");
|
|
79
57
|
assertUint32(n, "n");
|
|
80
58
|
assertProbability(epsilon, "epsilon");
|
|
81
59
|
return BloomFilter.#withN(bloomSizing(n, epsilon), n);
|
|
82
60
|
}
|
|
83
|
-
/**
|
|
84
|
-
* Builds a filter from `keys`, sized for their count at the target
|
|
85
|
-
* false-positive rate. The ergonomic entry point when the key set is already
|
|
86
|
-
* in hand; use {@link BloomFilter.create} to size for a count known ahead.
|
|
87
|
-
*
|
|
88
|
-
* @param keys - The keys to insert.
|
|
89
|
-
* @param epsilon - Target false-positive rate, e.g. `0.01` for 1%.
|
|
90
|
-
* @returns A new filter containing every key.
|
|
91
|
-
*/
|
|
92
61
|
static from(keys, epsilon) {
|
|
93
62
|
const arr = [...keys];
|
|
94
63
|
const f = BloomFilter.create(Math.max(1, arr.length), epsilon);
|
|
95
64
|
for (const k of arr) f.add(k);
|
|
96
65
|
return f;
|
|
97
66
|
}
|
|
98
|
-
/**
|
|
99
|
-
* Restores a filter from its {@link BloomFilter.toBytes} serialization.
|
|
100
|
-
*
|
|
101
|
-
* @param bytes - The serialized filter.
|
|
102
|
-
* @returns The reconstructed filter.
|
|
103
|
-
*/
|
|
104
67
|
static fromBytes(bytes) {
|
|
105
68
|
const { type, flags, body } = readHeader(bytes);
|
|
106
69
|
if (type !== TYPE) throw new SerializationError(`expected AMQF type ${String(TYPE)}, got ${String(type)}`);
|
|
@@ -120,10 +83,6 @@ var BloomFilter = class BloomFilter {
|
|
|
120
83
|
f.#bits.bytes.set(body.subarray(14));
|
|
121
84
|
return f;
|
|
122
85
|
}
|
|
123
|
-
/**
|
|
124
|
-
* Constructs a filter from low-level {@link BloomParams}. Prefer
|
|
125
|
-
* {@link BloomFilter.create} unless restoring a specific configuration.
|
|
126
|
-
*/
|
|
127
86
|
constructor({ m, k, seed = 0 }) {
|
|
128
87
|
assertPositiveInt(m, "m");
|
|
129
88
|
assertUint32(m, "m");
|
|
@@ -142,41 +101,24 @@ var BloomFilter = class BloomFilter {
|
|
|
142
101
|
f.#n = n;
|
|
143
102
|
return f;
|
|
144
103
|
}
|
|
145
|
-
/** Number of bits in the filter. */
|
|
146
104
|
get m() {
|
|
147
105
|
return this.#m;
|
|
148
106
|
}
|
|
149
|
-
/** Number of hash probes per key. */
|
|
150
107
|
get k() {
|
|
151
108
|
return this.#k;
|
|
152
109
|
}
|
|
153
|
-
/** Hash seed. */
|
|
154
110
|
get seed() {
|
|
155
111
|
return this.#seed;
|
|
156
112
|
}
|
|
157
|
-
/** Number of bits currently set. */
|
|
158
113
|
get length() {
|
|
159
114
|
return this.#bits.count();
|
|
160
115
|
}
|
|
161
|
-
/** Analytic design bits-per-key `m / n`. */
|
|
162
116
|
get bitsPerKey() {
|
|
163
117
|
return this.#m / this.#n;
|
|
164
118
|
}
|
|
165
|
-
/**
|
|
166
|
-
* Estimates the current false-positive rate from the actual fill,
|
|
167
|
-
* `(length / m) ** k`. This reflects how full the filter is right now, not
|
|
168
|
-
* the design target; it rises as keys are added.
|
|
169
|
-
*
|
|
170
|
-
* @returns The estimated false-positive rate, `0` for an empty filter.
|
|
171
|
-
*/
|
|
172
119
|
rate() {
|
|
173
120
|
return (this.length / this.#m) ** this.#k;
|
|
174
121
|
}
|
|
175
|
-
/**
|
|
176
|
-
* Serializes the filter to a portable little-endian byte layout.
|
|
177
|
-
*
|
|
178
|
-
* @returns The serialized filter, readable by {@link BloomFilter.fromBytes}.
|
|
179
|
-
*/
|
|
180
122
|
toBytes() {
|
|
181
123
|
const payload = this.#bits.bytes;
|
|
182
124
|
return writeFrame({
|
|
@@ -191,41 +133,15 @@ var BloomFilter = class BloomFilter {
|
|
|
191
133
|
body.set(payload, 14);
|
|
192
134
|
});
|
|
193
135
|
}
|
|
194
|
-
/**
|
|
195
|
-
* Tests structural equality: `true` when `other` serializes to identical
|
|
196
|
-
* bytes, meaning identical parameters and set bits.
|
|
197
|
-
*
|
|
198
|
-
* @param other - The filter to compare against.
|
|
199
|
-
* @returns `true` if the two filters are byte-for-byte identical.
|
|
200
|
-
*/
|
|
201
136
|
equals(other) {
|
|
202
137
|
return bytesEqual(this.toBytes(), other.toBytes());
|
|
203
138
|
}
|
|
204
|
-
/**
|
|
205
|
-
* Serializes the filter to a JSON-friendly envelope wrapping the base64 of
|
|
206
|
-
* {@link BloomFilter.toBytes}.
|
|
207
|
-
*
|
|
208
|
-
* @returns The envelope, readable by {@link BloomFilter.fromJSON}.
|
|
209
|
-
*/
|
|
210
139
|
toJSON() {
|
|
211
140
|
return toJSONEnvelope(this.toBytes());
|
|
212
141
|
}
|
|
213
|
-
/**
|
|
214
|
-
* Restores a filter from its {@link BloomFilter.toJSON} envelope.
|
|
215
|
-
*
|
|
216
|
-
* @param value - The JSON envelope.
|
|
217
|
-
* @returns The reconstructed filter.
|
|
218
|
-
*/
|
|
219
142
|
static fromJSON(value) {
|
|
220
143
|
return BloomFilter.fromBytes(fromJSONEnvelope(value));
|
|
221
144
|
}
|
|
222
|
-
/**
|
|
223
|
-
* Returns a new filter containing the union of this filter and `other`.
|
|
224
|
-
*
|
|
225
|
-
* @param other - A filter built with identical parameters.
|
|
226
|
-
* @returns A new filter reporting membership for keys in either input.
|
|
227
|
-
* @throws {@link BloomParamMismatchError} if the parameters differ.
|
|
228
|
-
*/
|
|
229
145
|
union(other) {
|
|
230
146
|
if (this.#m !== other.#m || this.#k !== other.#k || this.#seed !== other.#seed) throw new BloomParamMismatchError("cannot union Bloom filters whose parameters do not match");
|
|
231
147
|
const a = this.#bits.bytes;
|
|
@@ -240,21 +156,10 @@ var BloomFilter = class BloomFilter {
|
|
|
240
156
|
r.#bits.bytes.set(merged);
|
|
241
157
|
return r;
|
|
242
158
|
}
|
|
243
|
-
/**
|
|
244
|
-
* Adds a key to the set.
|
|
245
|
-
*
|
|
246
|
-
* @param key - The key to insert, as a string or bytes.
|
|
247
|
-
*/
|
|
248
159
|
add(key) {
|
|
249
160
|
probeInto(key, this.#k, this.#m, this.#seed, this.#scratch);
|
|
250
161
|
for (let i = 0; i < this.#k; i++) this.#bits.set(this.#scratch[i] ?? 0);
|
|
251
162
|
}
|
|
252
|
-
/**
|
|
253
|
-
* Tests whether a key is in the set.
|
|
254
|
-
*
|
|
255
|
-
* @param key - The key to test.
|
|
256
|
-
* @returns `true` if present (possibly a false positive); `false` guarantees absence.
|
|
257
|
-
*/
|
|
258
163
|
has(key) {
|
|
259
164
|
probeInto(key, this.#k, this.#m, this.#seed, this.#scratch);
|
|
260
165
|
for (let i = 0; i < this.#k; i++) if (!this.#bits.get(this.#scratch[i] ?? 0)) return false;
|
|
@@ -262,4 +167,4 @@ var BloomFilter = class BloomFilter {
|
|
|
262
167
|
}
|
|
263
168
|
};
|
|
264
169
|
//#endregion
|
|
265
|
-
export { BloomFilter, BloomParamMismatchError, ParamError, bloomSizing };
|
|
170
|
+
export { BadMagicError, BloomFilter, BloomParamMismatchError, ChecksumError, ParamError, SerializationError, TruncatedError, UnknownHashVariantError, UnknownVersionError, bloomSizing };
|
package/dist/fuse/index.cjs
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_serialize = require("../serialize-
|
|
2
|
+
const require_serialize = require("../serialize-CXnRWItH.cjs");
|
|
3
3
|
//#region src/fuse/fuse.ts
|
|
4
4
|
const ARITY = 3;
|
|
5
5
|
const TYPE_FUSE8 = 3;
|
|
6
6
|
const TYPE_FUSE16 = 4;
|
|
7
|
-
/** Thrown when binary fuse construction fails to converge on the key set. */
|
|
8
7
|
var BinaryFuseBuildError = class extends Error {
|
|
9
|
-
/** Discriminates this error from other `Error`s. */
|
|
10
8
|
name = "BinaryFuseBuildError";
|
|
11
9
|
};
|
|
12
10
|
const scratchHash = {
|
|
@@ -59,24 +57,10 @@ function computeParams(size) {
|
|
|
59
57
|
arrayLength
|
|
60
58
|
};
|
|
61
59
|
}
|
|
62
|
-
/**
|
|
63
|
-
* Bits stored per key by a binary fuse filter over `n` keys at a fingerprint
|
|
64
|
-
* width, without building one. Counts `n` as distinct keys, since a built
|
|
65
|
-
* filter sizes on its deduped hash count.
|
|
66
|
-
*
|
|
67
|
-
* @param n - Number of distinct keys.
|
|
68
|
-
* @param width - Fingerprint width in bits: `8` for {@link BinaryFuse8}, `16` for {@link BinaryFuse16}.
|
|
69
|
-
* @returns Bits per key (`0` for an empty filter).
|
|
70
|
-
*/
|
|
71
60
|
function fuseBitsPerKey(n, width) {
|
|
72
61
|
if (n === 0) return 0;
|
|
73
62
|
return computeParams(n).arrayLength * width / n;
|
|
74
63
|
}
|
|
75
|
-
/**
|
|
76
|
-
* Peel the 3-hypergraph and assign fingerprints so every key's XOR of its 3
|
|
77
|
-
* lanes equals its fingerprint. Retries with a bumped seed on a stall; returns
|
|
78
|
-
* the seed that succeeded.
|
|
79
|
-
*/
|
|
80
64
|
function buildFingerprints(fp, hashes, params, maxAttempts = 100) {
|
|
81
65
|
const size = hashes.length / 2;
|
|
82
66
|
const { seg, segMask, segCountLen, arrayLength } = params;
|
|
@@ -87,7 +71,7 @@ function buildFingerprints(fp, hashes, params, maxAttempts = 100) {
|
|
|
87
71
|
const orderLo = new Uint32Array(size);
|
|
88
72
|
const orderHi = new Uint32Array(size);
|
|
89
73
|
const orderIdx = new Uint32Array(size);
|
|
90
|
-
const pos =
|
|
74
|
+
const pos = new Uint32Array(3);
|
|
91
75
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
92
76
|
const seed = attempt;
|
|
93
77
|
counts.fill(0);
|
|
@@ -146,7 +130,7 @@ function buildFingerprints(fp, hashes, params, maxAttempts = 100) {
|
|
|
146
130
|
}
|
|
147
131
|
function buildState(keys, alloc) {
|
|
148
132
|
const hashList = [];
|
|
149
|
-
const seen =
|
|
133
|
+
const seen = new Set();
|
|
150
134
|
for (const key of keys) {
|
|
151
135
|
require_serialize.hash128KeyInto(key, 0, scratchHash);
|
|
152
136
|
const lo = scratchHash.w0 >>> 0;
|
|
@@ -204,10 +188,6 @@ function fuseStateFromBytes(bytes, expectedType) {
|
|
|
204
188
|
size
|
|
205
189
|
};
|
|
206
190
|
}
|
|
207
|
-
/**
|
|
208
|
-
* Shared behavior for the static binary fuse filters: an immutable,
|
|
209
|
-
* space-efficient membership filter built once from a fixed key set.
|
|
210
|
-
*/
|
|
211
191
|
var BinaryFuse = class {
|
|
212
192
|
#fp;
|
|
213
193
|
#seed;
|
|
@@ -215,7 +195,7 @@ var BinaryFuse = class {
|
|
|
215
195
|
#segMask;
|
|
216
196
|
#segCountLen;
|
|
217
197
|
#size;
|
|
218
|
-
#pos =
|
|
198
|
+
#pos = new Uint32Array(3);
|
|
219
199
|
constructor(state) {
|
|
220
200
|
this.#fp = state.fp;
|
|
221
201
|
this.#seed = state.seed;
|
|
@@ -224,23 +204,15 @@ var BinaryFuse = class {
|
|
|
224
204
|
this.#segCountLen = state.params.segCountLen;
|
|
225
205
|
this.#size = state.size;
|
|
226
206
|
}
|
|
227
|
-
/** Number of distinct keys the filter was built from. */
|
|
228
207
|
get size() {
|
|
229
208
|
return this.#size;
|
|
230
209
|
}
|
|
231
|
-
/** Hash seed selected during construction (may differ from 0 after a peel retry). */
|
|
232
210
|
get seed() {
|
|
233
211
|
return this.#seed;
|
|
234
212
|
}
|
|
235
|
-
/** Actual bits stored per key (`0` for an empty filter). */
|
|
236
213
|
get bitsPerKey() {
|
|
237
214
|
return this.#size === 0 ? 0 : this.#fp.byteLength * 8 / this.#size;
|
|
238
215
|
}
|
|
239
|
-
/**
|
|
240
|
-
* Serializes the filter to a portable little-endian byte layout.
|
|
241
|
-
*
|
|
242
|
-
* @returns The serialized filter, readable by the matching `fromBytes`.
|
|
243
|
-
*/
|
|
244
216
|
toBytes() {
|
|
245
217
|
const laneBytes = new Uint8Array(this.#fp.buffer, this.#fp.byteOffset, this.#fp.byteLength);
|
|
246
218
|
return require_serialize.writeFrame({
|
|
@@ -255,12 +227,6 @@ var BinaryFuse = class {
|
|
|
255
227
|
body.set(laneBytes, 16);
|
|
256
228
|
});
|
|
257
229
|
}
|
|
258
|
-
/**
|
|
259
|
-
* Tests whether a key is in the set.
|
|
260
|
-
*
|
|
261
|
-
* @param key - The key to test.
|
|
262
|
-
* @returns `true` if present (possibly a false positive); `false` guarantees absence.
|
|
263
|
-
*/
|
|
264
230
|
has(key) {
|
|
265
231
|
if (this.#fp.length === 0) return false;
|
|
266
232
|
require_serialize.hash128KeyInto(key, 0, scratchHash);
|
|
@@ -274,110 +240,43 @@ var BinaryFuse = class {
|
|
|
274
240
|
const p2 = this.#pos[2] ?? 0;
|
|
275
241
|
return ((mlo ^ mhi) & mask) === (((this.#fp[p0] ?? 0) ^ (this.#fp[p1] ?? 0) ^ (this.#fp[p2] ?? 0)) & mask);
|
|
276
242
|
}
|
|
277
|
-
/**
|
|
278
|
-
* Tests structural equality: `true` when `other` serializes to identical
|
|
279
|
-
* bytes. A {@link BinaryFuse8} and a {@link BinaryFuse16} are never equal,
|
|
280
|
-
* since their frames carry different type bytes.
|
|
281
|
-
*
|
|
282
|
-
* @param other - The filter to compare against.
|
|
283
|
-
* @returns `true` if the two filters are byte-for-byte identical.
|
|
284
|
-
*/
|
|
285
243
|
equals(other) {
|
|
286
244
|
return require_serialize.bytesEqual(this.toBytes(), other.toBytes());
|
|
287
245
|
}
|
|
288
|
-
/**
|
|
289
|
-
* Serializes the filter to a JSON-friendly envelope wrapping the base64 of
|
|
290
|
-
* the `toBytes` frame.
|
|
291
|
-
*
|
|
292
|
-
* @returns The envelope, readable by the matching `fromJSON`.
|
|
293
|
-
*/
|
|
294
246
|
toJSON() {
|
|
295
247
|
return require_serialize.toJSONEnvelope(this.toBytes());
|
|
296
248
|
}
|
|
297
249
|
};
|
|
298
|
-
/**
|
|
299
|
-
* A static 8-bit binary fuse filter: built once from a key set, then immutable.
|
|
300
|
-
* The most space-efficient option (~9 bits/key at ~0.39% false-positive rate).
|
|
301
|
-
*
|
|
302
|
-
* @example
|
|
303
|
-
* ```ts
|
|
304
|
-
* const filter = BinaryFuse8.from(["alice", "bob", "carol"]);
|
|
305
|
-
* filter.has("alice"); // true
|
|
306
|
-
* filter.size; // 3
|
|
307
|
-
* ```
|
|
308
|
-
*/
|
|
309
250
|
var BinaryFuse8 = class BinaryFuse8 extends BinaryFuse {
|
|
310
|
-
/**
|
|
311
|
-
* Builds a filter from the given keys; duplicates are ignored.
|
|
312
|
-
*
|
|
313
|
-
* @param keys - The complete set of keys to store.
|
|
314
|
-
* @returns A new immutable filter.
|
|
315
|
-
* @throws {@link BinaryFuseBuildError} if construction fails to converge.
|
|
316
|
-
*/
|
|
317
251
|
static from(keys) {
|
|
318
252
|
return new BinaryFuse8(buildState(keys, (n) => new Uint8Array(n)));
|
|
319
253
|
}
|
|
320
|
-
/**
|
|
321
|
-
* Restores a filter from its {@link BinaryFuse8.toBytes} serialization.
|
|
322
|
-
*
|
|
323
|
-
* @param bytes - The serialized filter.
|
|
324
|
-
* @returns The reconstructed filter.
|
|
325
|
-
*/
|
|
326
254
|
static fromBytes(bytes) {
|
|
327
255
|
return new BinaryFuse8(fuseStateFromBytes(bytes, TYPE_FUSE8));
|
|
328
256
|
}
|
|
329
|
-
/**
|
|
330
|
-
* Restores a filter from its {@link BinaryFuse8.toJSON} envelope.
|
|
331
|
-
*
|
|
332
|
-
* @param value - The JSON envelope.
|
|
333
|
-
* @returns The reconstructed filter.
|
|
334
|
-
*/
|
|
335
257
|
static fromJSON(value) {
|
|
336
258
|
return BinaryFuse8.fromBytes(require_serialize.fromJSONEnvelope(value));
|
|
337
259
|
}
|
|
338
260
|
};
|
|
339
|
-
/**
|
|
340
|
-
* A static 16-bit binary fuse filter: like {@link BinaryFuse8} but twice the
|
|
341
|
-
* space (~18 bits/key) for a far lower false-positive rate (~1/65536).
|
|
342
|
-
*
|
|
343
|
-
* @example
|
|
344
|
-
* ```ts
|
|
345
|
-
* const filter = BinaryFuse16.from(["alice", "bob", "carol"]);
|
|
346
|
-
* filter.has("alice"); // true
|
|
347
|
-
* ```
|
|
348
|
-
*/
|
|
349
261
|
var BinaryFuse16 = class BinaryFuse16 extends BinaryFuse {
|
|
350
|
-
/**
|
|
351
|
-
* Builds a filter from the given keys; duplicates are ignored.
|
|
352
|
-
*
|
|
353
|
-
* @param keys - The complete set of keys to store.
|
|
354
|
-
* @returns A new immutable filter.
|
|
355
|
-
* @throws {@link BinaryFuseBuildError} if construction fails to converge.
|
|
356
|
-
*/
|
|
357
262
|
static from(keys) {
|
|
358
263
|
return new BinaryFuse16(buildState(keys, (n) => new Uint16Array(n)));
|
|
359
264
|
}
|
|
360
|
-
/**
|
|
361
|
-
* Restores a filter from its {@link BinaryFuse16.toBytes} serialization.
|
|
362
|
-
*
|
|
363
|
-
* @param bytes - The serialized filter.
|
|
364
|
-
* @returns The reconstructed filter.
|
|
365
|
-
*/
|
|
366
265
|
static fromBytes(bytes) {
|
|
367
266
|
return new BinaryFuse16(fuseStateFromBytes(bytes, TYPE_FUSE16));
|
|
368
267
|
}
|
|
369
|
-
/**
|
|
370
|
-
* Restores a filter from its {@link BinaryFuse16.toJSON} envelope.
|
|
371
|
-
*
|
|
372
|
-
* @param value - The JSON envelope.
|
|
373
|
-
* @returns The reconstructed filter.
|
|
374
|
-
*/
|
|
375
268
|
static fromJSON(value) {
|
|
376
269
|
return BinaryFuse16.fromBytes(require_serialize.fromJSONEnvelope(value));
|
|
377
270
|
}
|
|
378
271
|
};
|
|
379
272
|
//#endregion
|
|
273
|
+
exports.BadMagicError = require_serialize.BadMagicError;
|
|
380
274
|
exports.BinaryFuse16 = BinaryFuse16;
|
|
381
275
|
exports.BinaryFuse8 = BinaryFuse8;
|
|
382
276
|
exports.BinaryFuseBuildError = BinaryFuseBuildError;
|
|
277
|
+
exports.ChecksumError = require_serialize.ChecksumError;
|
|
278
|
+
exports.SerializationError = require_serialize.SerializationError;
|
|
279
|
+
exports.TruncatedError = require_serialize.TruncatedError;
|
|
280
|
+
exports.UnknownHashVariantError = require_serialize.UnknownHashVariantError;
|
|
281
|
+
exports.UnknownVersionError = require_serialize.UnknownVersionError;
|
|
383
282
|
exports.fuseBitsPerKey = fuseBitsPerKey;
|
package/dist/fuse/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as TruncatedError, c as BytesLike, i as SerializationError, n as ChecksumError, o as UnknownHashVariantError, r as FilterJSON, s as UnknownVersionError, t as BadMagicError } from "../serialize-ChyWpB9F.cjs";
|
|
2
2
|
//#region src/fuse/fuse.d.ts
|
|
3
3
|
/** Thrown when binary fuse construction fails to converge on the key set. */
|
|
4
4
|
declare class BinaryFuseBuildError extends Error {
|
|
@@ -140,4 +140,4 @@ declare class BinaryFuse16 extends BinaryFuse {
|
|
|
140
140
|
static fromJSON(value: unknown): BinaryFuse16;
|
|
141
141
|
}
|
|
142
142
|
//#endregion
|
|
143
|
-
export { BinaryFuse16, BinaryFuse8, BinaryFuseBuildError, type FilterJSON, fuseBitsPerKey };
|
|
143
|
+
export { BadMagicError, BinaryFuse16, BinaryFuse8, BinaryFuseBuildError, ChecksumError, type FilterJSON, SerializationError, TruncatedError, UnknownHashVariantError, UnknownVersionError, fuseBitsPerKey };
|
package/dist/fuse/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as TruncatedError, c as BytesLike, i as SerializationError, n as ChecksumError, o as UnknownHashVariantError, r as FilterJSON, s as UnknownVersionError, t as BadMagicError } from "../serialize-ChyWpB9F.js";
|
|
2
2
|
//#region src/fuse/fuse.d.ts
|
|
3
3
|
/** Thrown when binary fuse construction fails to converge on the key set. */
|
|
4
4
|
declare class BinaryFuseBuildError extends Error {
|
|
@@ -140,4 +140,4 @@ declare class BinaryFuse16 extends BinaryFuse {
|
|
|
140
140
|
static fromJSON(value: unknown): BinaryFuse16;
|
|
141
141
|
}
|
|
142
142
|
//#endregion
|
|
143
|
-
export { BinaryFuse16, BinaryFuse8, BinaryFuseBuildError, type FilterJSON, fuseBitsPerKey };
|
|
143
|
+
export { BadMagicError, BinaryFuse16, BinaryFuse8, BinaryFuseBuildError, ChecksumError, type FilterJSON, SerializationError, TruncatedError, UnknownHashVariantError, UnknownVersionError, fuseBitsPerKey };
|