distillate 0.5.0 → 0.7.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 +9 -9
- package/dist/blocked/index.cjs +113 -38
- package/dist/blocked/index.d.cts +55 -3
- package/dist/blocked/index.d.ts +55 -3
- package/dist/blocked/index.js +112 -39
- package/dist/bloom/index.cjs +71 -28
- package/dist/bloom/index.d.cts +45 -2
- package/dist/bloom/index.d.ts +45 -2
- package/dist/bloom/index.js +71 -29
- package/dist/fuse/index.cjs +77 -19
- package/dist/fuse/index.d.cts +44 -2
- package/dist/fuse/index.d.ts +44 -2
- package/dist/fuse/index.js +77 -20
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/{params-J8p3bKq5.cjs → params--8CNXYWu.cjs} +10 -0
- package/dist/{params-ChTRNxM9.js → params-BrWuBC2A.js} +5 -1
- package/dist/serialize-BIIKUHH6.cjs +515 -0
- package/dist/serialize-BnwtzcMw.js +414 -0
- package/dist/serialize-DRKh6QOr.d.cts +15 -0
- package/dist/serialize-DRKh6QOr.d.ts +15 -0
- package/package.json +8 -31
- package/dist/bytes-DCuYtUVS.d.cts +0 -4
- package/dist/bytes-DCuYtUVS.d.ts +0 -4
- package/dist/serialize-BQ2UzZqq.js +0 -354
- package/dist/serialize-fa-pEUGq.cjs +0 -437
package/dist/bloom/index.js
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { a as
|
|
1
|
+
import { a as bytesEqual, c as toJSONEnvelope, g as probeInto, i as assertMinBodyLength, l as writeFrame, n as UnknownHashVariantError, o as fromJSONEnvelope, r as assertBodyLength, s as readHeader, t as SerializationError } from "../serialize-BnwtzcMw.js";
|
|
2
|
+
import { a as assertUint16, i as assertProbability, o as assertUint32, r as assertPositiveInt, t as ParamError } from "../params-BrWuBC2A.js";
|
|
3
3
|
//#region src/core/bitset.ts
|
|
4
4
|
var BitSetRangeError = class extends RangeError {
|
|
5
5
|
name = "BitSetRangeError";
|
|
6
6
|
};
|
|
7
7
|
const MAX_BITS = 2 ** 32;
|
|
8
|
-
var BitSet = class
|
|
8
|
+
var BitSet = class {
|
|
9
9
|
#bits;
|
|
10
|
-
static fromBytes(bytes) {
|
|
11
|
-
const bs = new BitSet(bytes.length * 8);
|
|
12
|
-
bs.#bits.set(bytes);
|
|
13
|
-
return bs;
|
|
14
|
-
}
|
|
15
10
|
constructor(nbits) {
|
|
16
11
|
if (nbits > MAX_BITS) throw new BitSetRangeError(`BitSet capacity ${String(nbits)} exceeds the 2^32-bit limit`);
|
|
17
12
|
this.#bits = new Uint8Array(Math.ceil(nbits / 8));
|
|
@@ -38,7 +33,7 @@ var BitSet = class BitSet {
|
|
|
38
33
|
//#endregion
|
|
39
34
|
//#region src/core/sizing.ts
|
|
40
35
|
/** Optimal Bloom-filter sizing: `m` bits and `k` hashes for `n` items at target FPR `epsilon`. */
|
|
41
|
-
function
|
|
36
|
+
function bloomSizing(n, epsilon) {
|
|
42
37
|
const m = Math.ceil(-n * Math.log(epsilon) / (Math.LN2 * Math.LN2));
|
|
43
38
|
return {
|
|
44
39
|
m,
|
|
@@ -81,9 +76,23 @@ var BloomFilter = class BloomFilter {
|
|
|
81
76
|
*/
|
|
82
77
|
static create(n, epsilon) {
|
|
83
78
|
assertPositiveInt(n, "n");
|
|
79
|
+
assertUint32(n, "n");
|
|
84
80
|
assertProbability(epsilon, "epsilon");
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
return BloomFilter.#withN(bloomSizing(n, epsilon), n);
|
|
82
|
+
}
|
|
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
|
+
static from(keys, epsilon) {
|
|
93
|
+
const arr = [...keys];
|
|
94
|
+
const f = BloomFilter.create(Math.max(1, arr.length), epsilon);
|
|
95
|
+
for (const k of arr) f.add(k);
|
|
87
96
|
return f;
|
|
88
97
|
}
|
|
89
98
|
/**
|
|
@@ -95,7 +104,7 @@ var BloomFilter = class BloomFilter {
|
|
|
95
104
|
static fromBytes(bytes) {
|
|
96
105
|
const { type, flags, body } = readHeader(bytes);
|
|
97
106
|
if (type !== TYPE) throw new SerializationError(`expected AMQF type ${String(TYPE)}, got ${String(type)}`);
|
|
98
|
-
if ((flags & 15) !==
|
|
107
|
+
if ((flags & 15) !== 0) throw new UnknownHashVariantError(`unsupported hash variant ${String(flags & 15)}`);
|
|
99
108
|
assertMinBodyLength(body.length, 14, "bloom");
|
|
100
109
|
const dv = new DataView(body.buffer, body.byteOffset, body.byteLength);
|
|
101
110
|
const m = dv.getUint32(0, true);
|
|
@@ -103,12 +112,11 @@ var BloomFilter = class BloomFilter {
|
|
|
103
112
|
const seed = dv.getUint32(6, true);
|
|
104
113
|
const n = dv.getUint32(10, true);
|
|
105
114
|
assertBodyLength(body.length, 14 + Math.ceil(m / 8), "bloom");
|
|
106
|
-
const f =
|
|
115
|
+
const f = BloomFilter.#withN({
|
|
107
116
|
m,
|
|
108
117
|
k,
|
|
109
118
|
seed
|
|
110
|
-
});
|
|
111
|
-
f.#n = n;
|
|
119
|
+
}, n);
|
|
112
120
|
f.#bits.bytes.set(body.subarray(14));
|
|
113
121
|
return f;
|
|
114
122
|
}
|
|
@@ -118,7 +126,9 @@ var BloomFilter = class BloomFilter {
|
|
|
118
126
|
*/
|
|
119
127
|
constructor({ m, k, seed = 0 }) {
|
|
120
128
|
assertPositiveInt(m, "m");
|
|
129
|
+
assertUint32(m, "m");
|
|
121
130
|
assertPositiveInt(k, "k");
|
|
131
|
+
assertUint16(k, "k");
|
|
122
132
|
assertUint32(seed, "seed");
|
|
123
133
|
this.#bits = new BitSet(m);
|
|
124
134
|
this.#m = m;
|
|
@@ -127,6 +137,11 @@ var BloomFilter = class BloomFilter {
|
|
|
127
137
|
this.#scratch = new Uint32Array(k);
|
|
128
138
|
this.#n = Math.round(m * Math.LN2 / k);
|
|
129
139
|
}
|
|
140
|
+
static #withN(params, n) {
|
|
141
|
+
const f = new BloomFilter(params);
|
|
142
|
+
f.#n = n;
|
|
143
|
+
return f;
|
|
144
|
+
}
|
|
130
145
|
/** Number of bits in the filter. */
|
|
131
146
|
get m() {
|
|
132
147
|
return this.#m;
|
|
@@ -164,18 +179,45 @@ var BloomFilter = class BloomFilter {
|
|
|
164
179
|
*/
|
|
165
180
|
toBytes() {
|
|
166
181
|
const payload = this.#bits.bytes;
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
dv.setUint32(0, this.#m, true);
|
|
170
|
-
dv.setUint16(4, this.#k, true);
|
|
171
|
-
dv.setUint32(6, this.#seed, true);
|
|
172
|
-
dv.setUint32(10, this.#n, true);
|
|
173
|
-
body.set(payload, 14);
|
|
174
|
-
return writeHeader({
|
|
175
|
-
version: 2,
|
|
182
|
+
return writeFrame({
|
|
183
|
+
version: 3,
|
|
176
184
|
type: TYPE,
|
|
177
|
-
flags:
|
|
178
|
-
}, body)
|
|
185
|
+
flags: 0
|
|
186
|
+
}, 14 + payload.length, (body, dv) => {
|
|
187
|
+
dv.setUint32(0, this.#m, true);
|
|
188
|
+
dv.setUint16(4, this.#k, true);
|
|
189
|
+
dv.setUint32(6, this.#seed, true);
|
|
190
|
+
dv.setUint32(10, this.#n, true);
|
|
191
|
+
body.set(payload, 14);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
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
|
+
equals(other) {
|
|
202
|
+
return bytesEqual(this.toBytes(), other.toBytes());
|
|
203
|
+
}
|
|
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
|
+
toJSON() {
|
|
211
|
+
return toJSONEnvelope(this.toBytes());
|
|
212
|
+
}
|
|
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
|
+
static fromJSON(value) {
|
|
220
|
+
return BloomFilter.fromBytes(fromJSONEnvelope(value));
|
|
179
221
|
}
|
|
180
222
|
/**
|
|
181
223
|
* Returns a new filter containing the union of this filter and `other`.
|
|
@@ -190,11 +232,11 @@ var BloomFilter = class BloomFilter {
|
|
|
190
232
|
const b = other.#bits.bytes;
|
|
191
233
|
const merged = new Uint8Array(a.length);
|
|
192
234
|
for (let i = 0; i < a.length; i++) merged[i] = (a[i] ?? 0) | (b[i] ?? 0);
|
|
193
|
-
const r =
|
|
235
|
+
const r = BloomFilter.#withN({
|
|
194
236
|
m: this.#m,
|
|
195
237
|
k: this.#k,
|
|
196
238
|
seed: this.#seed
|
|
197
|
-
});
|
|
239
|
+
}, this.#n);
|
|
198
240
|
r.#bits.bytes.set(merged);
|
|
199
241
|
return r;
|
|
200
242
|
}
|
|
@@ -220,4 +262,4 @@ var BloomFilter = class BloomFilter {
|
|
|
220
262
|
}
|
|
221
263
|
};
|
|
222
264
|
//#endregion
|
|
223
|
-
export { BloomFilter, BloomParamMismatchError, ParamError };
|
|
265
|
+
export { BloomFilter, BloomParamMismatchError, ParamError, bloomSizing };
|
package/dist/fuse/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_serialize = require("../serialize-
|
|
2
|
+
const require_serialize = require("../serialize-BIIKUHH6.cjs");
|
|
3
3
|
//#region src/fuse/fuse.ts
|
|
4
4
|
const ARITY = 3;
|
|
5
5
|
const TYPE_FUSE8 = 3;
|
|
@@ -10,10 +10,10 @@ var BinaryFuseBuildError = class extends Error {
|
|
|
10
10
|
name = "BinaryFuseBuildError";
|
|
11
11
|
};
|
|
12
12
|
const scratchHash = {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
w0: 0,
|
|
14
|
+
w1: 0,
|
|
15
|
+
w2: 0,
|
|
16
|
+
w3: 0
|
|
17
17
|
};
|
|
18
18
|
function mixSeed(lo, hi, seed) {
|
|
19
19
|
const l = (lo >>> 0) + (seed >>> 0);
|
|
@@ -60,6 +60,19 @@ function computeParams(size) {
|
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
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
|
+
function fuseBitsPerKey(n, width) {
|
|
72
|
+
if (n === 0) return 0;
|
|
73
|
+
return computeParams(n).arrayLength * width / n;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
63
76
|
* Peel the 3-hypergraph and assign fingerprints so every key's XOR of its 3
|
|
64
77
|
* lanes equals its fingerprint. Retries with a bumped seed on a stall; returns
|
|
65
78
|
* the seed that succeeded.
|
|
@@ -136,8 +149,8 @@ function buildState(keys, alloc) {
|
|
|
136
149
|
const seen = /* @__PURE__ */ new Set();
|
|
137
150
|
for (const key of keys) {
|
|
138
151
|
require_serialize.hash128KeyInto(key, 0, scratchHash);
|
|
139
|
-
const lo = scratchHash.
|
|
140
|
-
const hi = scratchHash.
|
|
152
|
+
const lo = scratchHash.w0 >>> 0;
|
|
153
|
+
const hi = scratchHash.w1 >>> 0;
|
|
141
154
|
const id = `${String(lo)},${String(hi)}`;
|
|
142
155
|
if (seen.has(id)) continue;
|
|
143
156
|
seen.add(id);
|
|
@@ -161,14 +174,17 @@ function buildState(keys, alloc) {
|
|
|
161
174
|
};
|
|
162
175
|
}
|
|
163
176
|
function fuseStateFromBytes(bytes, expectedType) {
|
|
164
|
-
const { type, body } = require_serialize.readHeader(bytes);
|
|
177
|
+
const { type, flags, body } = require_serialize.readHeader(bytes);
|
|
165
178
|
if (type !== expectedType) throw new require_serialize.SerializationError(`expected AMQF type ${String(expectedType)}, got ${String(type)}`);
|
|
179
|
+
if ((flags & 15) !== 0) throw new require_serialize.UnknownHashVariantError(`unsupported hash variant ${String(flags & 15)}`);
|
|
166
180
|
require_serialize.assertMinBodyLength(body.length, 16, "fuse");
|
|
167
181
|
const dv = new DataView(body.buffer, body.byteOffset, body.byteLength);
|
|
168
182
|
const seed = dv.getUint32(0, true);
|
|
169
183
|
const seg = dv.getUint32(4, true);
|
|
170
184
|
const segCountLen = dv.getUint32(8, true);
|
|
171
185
|
const size = dv.getUint32(12, true);
|
|
186
|
+
if (seg === 0 || (seg & seg - 1) !== 0 || seg > 1 << 18) throw new require_serialize.SerializationError(`invalid fuse segment length ${String(seg)}`);
|
|
187
|
+
if (segCountLen % seg !== 0) throw new require_serialize.SerializationError(`fuse segment count length ${String(segCountLen)} is not a multiple of segment length ${String(seg)}`);
|
|
172
188
|
const bpe = expectedType === TYPE_FUSE8 ? 1 : 2;
|
|
173
189
|
const expectedArrayLength = size === 0 ? 0 : segCountLen + 2 * seg;
|
|
174
190
|
require_serialize.assertBodyLength(body.length, 16 + expectedArrayLength * bpe, "fuse");
|
|
@@ -212,6 +228,10 @@ var BinaryFuse = class {
|
|
|
212
228
|
get size() {
|
|
213
229
|
return this.#size;
|
|
214
230
|
}
|
|
231
|
+
/** Hash seed selected during construction (may differ from 0 after a peel retry). */
|
|
232
|
+
get seed() {
|
|
233
|
+
return this.#seed;
|
|
234
|
+
}
|
|
215
235
|
/** Actual bits stored per key (`0` for an empty filter). */
|
|
216
236
|
get bitsPerKey() {
|
|
217
237
|
return this.#size === 0 ? 0 : this.#fp.byteLength * 8 / this.#size;
|
|
@@ -223,18 +243,17 @@ var BinaryFuse = class {
|
|
|
223
243
|
*/
|
|
224
244
|
toBytes() {
|
|
225
245
|
const laneBytes = new Uint8Array(this.#fp.buffer, this.#fp.byteOffset, this.#fp.byteLength);
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
dv.setUint32(0, this.#seed, true);
|
|
229
|
-
dv.setUint32(4, this.#seg, true);
|
|
230
|
-
dv.setUint32(8, this.#segCountLen, true);
|
|
231
|
-
dv.setUint32(12, this.#size, true);
|
|
232
|
-
body.set(laneBytes, 16);
|
|
233
|
-
return require_serialize.writeHeader({
|
|
234
|
-
version: 2,
|
|
246
|
+
return require_serialize.writeFrame({
|
|
247
|
+
version: 3,
|
|
235
248
|
type: this.#fp.BYTES_PER_ELEMENT === 1 ? TYPE_FUSE8 : TYPE_FUSE16,
|
|
236
249
|
flags: 0
|
|
237
|
-
}, body)
|
|
250
|
+
}, 16 + laneBytes.length, (body, dv) => {
|
|
251
|
+
dv.setUint32(0, this.#seed, true);
|
|
252
|
+
dv.setUint32(4, this.#seg, true);
|
|
253
|
+
dv.setUint32(8, this.#segCountLen, true);
|
|
254
|
+
dv.setUint32(12, this.#size, true);
|
|
255
|
+
body.set(laneBytes, 16);
|
|
256
|
+
});
|
|
238
257
|
}
|
|
239
258
|
/**
|
|
240
259
|
* Tests whether a key is in the set.
|
|
@@ -245,7 +264,7 @@ var BinaryFuse = class {
|
|
|
245
264
|
has(key) {
|
|
246
265
|
if (this.#fp.length === 0) return false;
|
|
247
266
|
require_serialize.hash128KeyInto(key, 0, scratchHash);
|
|
248
|
-
mixSeed(scratchHash.
|
|
267
|
+
mixSeed(scratchHash.w0 >>> 0, scratchHash.w1 >>> 0, this.#seed);
|
|
249
268
|
const mlo = require_serialize.RLO;
|
|
250
269
|
const mhi = require_serialize.RHI;
|
|
251
270
|
positionsInto(mlo, mhi, this.#seg, this.#segMask, this.#segCountLen, this.#pos);
|
|
@@ -255,6 +274,26 @@ var BinaryFuse = class {
|
|
|
255
274
|
const p2 = this.#pos[2] ?? 0;
|
|
256
275
|
return ((mlo ^ mhi) & mask) === (((this.#fp[p0] ?? 0) ^ (this.#fp[p1] ?? 0) ^ (this.#fp[p2] ?? 0)) & mask);
|
|
257
276
|
}
|
|
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
|
+
equals(other) {
|
|
286
|
+
return require_serialize.bytesEqual(this.toBytes(), other.toBytes());
|
|
287
|
+
}
|
|
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
|
+
toJSON() {
|
|
295
|
+
return require_serialize.toJSONEnvelope(this.toBytes());
|
|
296
|
+
}
|
|
258
297
|
};
|
|
259
298
|
/**
|
|
260
299
|
* A static 8-bit binary fuse filter: built once from a key set, then immutable.
|
|
@@ -287,6 +326,15 @@ var BinaryFuse8 = class BinaryFuse8 extends BinaryFuse {
|
|
|
287
326
|
static fromBytes(bytes) {
|
|
288
327
|
return new BinaryFuse8(fuseStateFromBytes(bytes, TYPE_FUSE8));
|
|
289
328
|
}
|
|
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
|
+
static fromJSON(value) {
|
|
336
|
+
return BinaryFuse8.fromBytes(require_serialize.fromJSONEnvelope(value));
|
|
337
|
+
}
|
|
290
338
|
};
|
|
291
339
|
/**
|
|
292
340
|
* A static 16-bit binary fuse filter: like {@link BinaryFuse8} but twice the
|
|
@@ -318,8 +366,18 @@ var BinaryFuse16 = class BinaryFuse16 extends BinaryFuse {
|
|
|
318
366
|
static fromBytes(bytes) {
|
|
319
367
|
return new BinaryFuse16(fuseStateFromBytes(bytes, TYPE_FUSE16));
|
|
320
368
|
}
|
|
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
|
+
static fromJSON(value) {
|
|
376
|
+
return BinaryFuse16.fromBytes(require_serialize.fromJSONEnvelope(value));
|
|
377
|
+
}
|
|
321
378
|
};
|
|
322
379
|
//#endregion
|
|
323
380
|
exports.BinaryFuse16 = BinaryFuse16;
|
|
324
381
|
exports.BinaryFuse8 = BinaryFuse8;
|
|
325
382
|
exports.BinaryFuseBuildError = BinaryFuseBuildError;
|
|
383
|
+
exports.fuseBitsPerKey = fuseBitsPerKey;
|
package/dist/fuse/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as BytesLike, t as FilterJSON } from "../serialize-DRKh6QOr.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 {
|
|
@@ -11,6 +11,16 @@ interface FuseParams {
|
|
|
11
11
|
segCountLen: number;
|
|
12
12
|
arrayLength: number;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Bits stored per key by a binary fuse filter over `n` keys at a fingerprint
|
|
16
|
+
* width, without building one. Counts `n` as distinct keys, since a built
|
|
17
|
+
* filter sizes on its deduped hash count.
|
|
18
|
+
*
|
|
19
|
+
* @param n - Number of distinct keys.
|
|
20
|
+
* @param width - Fingerprint width in bits: `8` for {@link BinaryFuse8}, `16` for {@link BinaryFuse16}.
|
|
21
|
+
* @returns Bits per key (`0` for an empty filter).
|
|
22
|
+
*/
|
|
23
|
+
declare function fuseBitsPerKey(n: number, width: 8 | 16): number;
|
|
14
24
|
interface FuseState {
|
|
15
25
|
fp: Uint8Array | Uint16Array;
|
|
16
26
|
seed: number;
|
|
@@ -26,6 +36,8 @@ declare abstract class BinaryFuse {
|
|
|
26
36
|
protected constructor(state: FuseState);
|
|
27
37
|
/** Number of distinct keys the filter was built from. */
|
|
28
38
|
get size(): number;
|
|
39
|
+
/** Hash seed selected during construction (may differ from 0 after a peel retry). */
|
|
40
|
+
get seed(): number;
|
|
29
41
|
/** Actual bits stored per key (`0` for an empty filter). */
|
|
30
42
|
get bitsPerKey(): number;
|
|
31
43
|
/**
|
|
@@ -41,6 +53,22 @@ declare abstract class BinaryFuse {
|
|
|
41
53
|
* @returns `true` if present (possibly a false positive); `false` guarantees absence.
|
|
42
54
|
*/
|
|
43
55
|
has(key: BytesLike): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Tests structural equality: `true` when `other` serializes to identical
|
|
58
|
+
* bytes. A {@link BinaryFuse8} and a {@link BinaryFuse16} are never equal,
|
|
59
|
+
* since their frames carry different type bytes.
|
|
60
|
+
*
|
|
61
|
+
* @param other - The filter to compare against.
|
|
62
|
+
* @returns `true` if the two filters are byte-for-byte identical.
|
|
63
|
+
*/
|
|
64
|
+
equals(other: BinaryFuse8 | BinaryFuse16): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Serializes the filter to a JSON-friendly envelope wrapping the base64 of
|
|
67
|
+
* the `toBytes` frame.
|
|
68
|
+
*
|
|
69
|
+
* @returns The envelope, readable by the matching `fromJSON`.
|
|
70
|
+
*/
|
|
71
|
+
toJSON(): FilterJSON;
|
|
44
72
|
}
|
|
45
73
|
/**
|
|
46
74
|
* A static 8-bit binary fuse filter: built once from a key set, then immutable.
|
|
@@ -69,6 +97,13 @@ declare class BinaryFuse8 extends BinaryFuse {
|
|
|
69
97
|
* @returns The reconstructed filter.
|
|
70
98
|
*/
|
|
71
99
|
static fromBytes(bytes: Uint8Array): BinaryFuse8;
|
|
100
|
+
/**
|
|
101
|
+
* Restores a filter from its {@link BinaryFuse8.toJSON} envelope.
|
|
102
|
+
*
|
|
103
|
+
* @param value - The JSON envelope.
|
|
104
|
+
* @returns The reconstructed filter.
|
|
105
|
+
*/
|
|
106
|
+
static fromJSON(value: unknown): BinaryFuse8;
|
|
72
107
|
}
|
|
73
108
|
/**
|
|
74
109
|
* A static 16-bit binary fuse filter: like {@link BinaryFuse8} but twice the
|
|
@@ -96,6 +131,13 @@ declare class BinaryFuse16 extends BinaryFuse {
|
|
|
96
131
|
* @returns The reconstructed filter.
|
|
97
132
|
*/
|
|
98
133
|
static fromBytes(bytes: Uint8Array): BinaryFuse16;
|
|
134
|
+
/**
|
|
135
|
+
* Restores a filter from its {@link BinaryFuse16.toJSON} envelope.
|
|
136
|
+
*
|
|
137
|
+
* @param value - The JSON envelope.
|
|
138
|
+
* @returns The reconstructed filter.
|
|
139
|
+
*/
|
|
140
|
+
static fromJSON(value: unknown): BinaryFuse16;
|
|
99
141
|
}
|
|
100
142
|
//#endregion
|
|
101
|
-
export { BinaryFuse16, BinaryFuse8, BinaryFuseBuildError };
|
|
143
|
+
export { BinaryFuse16, BinaryFuse8, BinaryFuseBuildError, type FilterJSON, fuseBitsPerKey };
|
package/dist/fuse/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as BytesLike, t as FilterJSON } from "../serialize-DRKh6QOr.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 {
|
|
@@ -11,6 +11,16 @@ interface FuseParams {
|
|
|
11
11
|
segCountLen: number;
|
|
12
12
|
arrayLength: number;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Bits stored per key by a binary fuse filter over `n` keys at a fingerprint
|
|
16
|
+
* width, without building one. Counts `n` as distinct keys, since a built
|
|
17
|
+
* filter sizes on its deduped hash count.
|
|
18
|
+
*
|
|
19
|
+
* @param n - Number of distinct keys.
|
|
20
|
+
* @param width - Fingerprint width in bits: `8` for {@link BinaryFuse8}, `16` for {@link BinaryFuse16}.
|
|
21
|
+
* @returns Bits per key (`0` for an empty filter).
|
|
22
|
+
*/
|
|
23
|
+
declare function fuseBitsPerKey(n: number, width: 8 | 16): number;
|
|
14
24
|
interface FuseState {
|
|
15
25
|
fp: Uint8Array | Uint16Array;
|
|
16
26
|
seed: number;
|
|
@@ -26,6 +36,8 @@ declare abstract class BinaryFuse {
|
|
|
26
36
|
protected constructor(state: FuseState);
|
|
27
37
|
/** Number of distinct keys the filter was built from. */
|
|
28
38
|
get size(): number;
|
|
39
|
+
/** Hash seed selected during construction (may differ from 0 after a peel retry). */
|
|
40
|
+
get seed(): number;
|
|
29
41
|
/** Actual bits stored per key (`0` for an empty filter). */
|
|
30
42
|
get bitsPerKey(): number;
|
|
31
43
|
/**
|
|
@@ -41,6 +53,22 @@ declare abstract class BinaryFuse {
|
|
|
41
53
|
* @returns `true` if present (possibly a false positive); `false` guarantees absence.
|
|
42
54
|
*/
|
|
43
55
|
has(key: BytesLike): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Tests structural equality: `true` when `other` serializes to identical
|
|
58
|
+
* bytes. A {@link BinaryFuse8} and a {@link BinaryFuse16} are never equal,
|
|
59
|
+
* since their frames carry different type bytes.
|
|
60
|
+
*
|
|
61
|
+
* @param other - The filter to compare against.
|
|
62
|
+
* @returns `true` if the two filters are byte-for-byte identical.
|
|
63
|
+
*/
|
|
64
|
+
equals(other: BinaryFuse8 | BinaryFuse16): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Serializes the filter to a JSON-friendly envelope wrapping the base64 of
|
|
67
|
+
* the `toBytes` frame.
|
|
68
|
+
*
|
|
69
|
+
* @returns The envelope, readable by the matching `fromJSON`.
|
|
70
|
+
*/
|
|
71
|
+
toJSON(): FilterJSON;
|
|
44
72
|
}
|
|
45
73
|
/**
|
|
46
74
|
* A static 8-bit binary fuse filter: built once from a key set, then immutable.
|
|
@@ -69,6 +97,13 @@ declare class BinaryFuse8 extends BinaryFuse {
|
|
|
69
97
|
* @returns The reconstructed filter.
|
|
70
98
|
*/
|
|
71
99
|
static fromBytes(bytes: Uint8Array): BinaryFuse8;
|
|
100
|
+
/**
|
|
101
|
+
* Restores a filter from its {@link BinaryFuse8.toJSON} envelope.
|
|
102
|
+
*
|
|
103
|
+
* @param value - The JSON envelope.
|
|
104
|
+
* @returns The reconstructed filter.
|
|
105
|
+
*/
|
|
106
|
+
static fromJSON(value: unknown): BinaryFuse8;
|
|
72
107
|
}
|
|
73
108
|
/**
|
|
74
109
|
* A static 16-bit binary fuse filter: like {@link BinaryFuse8} but twice the
|
|
@@ -96,6 +131,13 @@ declare class BinaryFuse16 extends BinaryFuse {
|
|
|
96
131
|
* @returns The reconstructed filter.
|
|
97
132
|
*/
|
|
98
133
|
static fromBytes(bytes: Uint8Array): BinaryFuse16;
|
|
134
|
+
/**
|
|
135
|
+
* Restores a filter from its {@link BinaryFuse16.toJSON} envelope.
|
|
136
|
+
*
|
|
137
|
+
* @param value - The JSON envelope.
|
|
138
|
+
* @returns The reconstructed filter.
|
|
139
|
+
*/
|
|
140
|
+
static fromJSON(value: unknown): BinaryFuse16;
|
|
99
141
|
}
|
|
100
142
|
//#endregion
|
|
101
|
-
export { BinaryFuse16, BinaryFuse8, BinaryFuseBuildError };
|
|
143
|
+
export { BinaryFuse16, BinaryFuse8, BinaryFuseBuildError, type FilterJSON, fuseBitsPerKey };
|