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/fuse/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as bytesEqual, c as toJSONEnvelope, d as RLO, f as fmix64, h as mul64, i as assertMinBodyLength, l as writeFrame, n as UnknownHashVariantError, o as fromJSONEnvelope, p as hash128KeyInto, r as assertBodyLength, s as readHeader, t as SerializationError, u as RHI } from "../serialize-BnwtzcMw.js";
|
|
2
2
|
//#region src/fuse/fuse.ts
|
|
3
3
|
const ARITY = 3;
|
|
4
4
|
const TYPE_FUSE8 = 3;
|
|
@@ -9,10 +9,10 @@ var BinaryFuseBuildError = class extends Error {
|
|
|
9
9
|
name = "BinaryFuseBuildError";
|
|
10
10
|
};
|
|
11
11
|
const scratchHash = {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
w0: 0,
|
|
13
|
+
w1: 0,
|
|
14
|
+
w2: 0,
|
|
15
|
+
w3: 0
|
|
16
16
|
};
|
|
17
17
|
function mixSeed(lo, hi, seed) {
|
|
18
18
|
const l = (lo >>> 0) + (seed >>> 0);
|
|
@@ -59,6 +59,19 @@ function computeParams(size) {
|
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
|
+
* Bits stored per key by a binary fuse filter over `n` keys at a fingerprint
|
|
63
|
+
* width, without building one. Counts `n` as distinct keys, since a built
|
|
64
|
+
* filter sizes on its deduped hash count.
|
|
65
|
+
*
|
|
66
|
+
* @param n - Number of distinct keys.
|
|
67
|
+
* @param width - Fingerprint width in bits: `8` for {@link BinaryFuse8}, `16` for {@link BinaryFuse16}.
|
|
68
|
+
* @returns Bits per key (`0` for an empty filter).
|
|
69
|
+
*/
|
|
70
|
+
function fuseBitsPerKey(n, width) {
|
|
71
|
+
if (n === 0) return 0;
|
|
72
|
+
return computeParams(n).arrayLength * width / n;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
62
75
|
* Peel the 3-hypergraph and assign fingerprints so every key's XOR of its 3
|
|
63
76
|
* lanes equals its fingerprint. Retries with a bumped seed on a stall; returns
|
|
64
77
|
* the seed that succeeded.
|
|
@@ -135,8 +148,8 @@ function buildState(keys, alloc) {
|
|
|
135
148
|
const seen = /* @__PURE__ */ new Set();
|
|
136
149
|
for (const key of keys) {
|
|
137
150
|
hash128KeyInto(key, 0, scratchHash);
|
|
138
|
-
const lo = scratchHash.
|
|
139
|
-
const hi = scratchHash.
|
|
151
|
+
const lo = scratchHash.w0 >>> 0;
|
|
152
|
+
const hi = scratchHash.w1 >>> 0;
|
|
140
153
|
const id = `${String(lo)},${String(hi)}`;
|
|
141
154
|
if (seen.has(id)) continue;
|
|
142
155
|
seen.add(id);
|
|
@@ -160,14 +173,17 @@ function buildState(keys, alloc) {
|
|
|
160
173
|
};
|
|
161
174
|
}
|
|
162
175
|
function fuseStateFromBytes(bytes, expectedType) {
|
|
163
|
-
const { type, body } = readHeader(bytes);
|
|
176
|
+
const { type, flags, body } = readHeader(bytes);
|
|
164
177
|
if (type !== expectedType) throw new SerializationError(`expected AMQF type ${String(expectedType)}, got ${String(type)}`);
|
|
178
|
+
if ((flags & 15) !== 0) throw new UnknownHashVariantError(`unsupported hash variant ${String(flags & 15)}`);
|
|
165
179
|
assertMinBodyLength(body.length, 16, "fuse");
|
|
166
180
|
const dv = new DataView(body.buffer, body.byteOffset, body.byteLength);
|
|
167
181
|
const seed = dv.getUint32(0, true);
|
|
168
182
|
const seg = dv.getUint32(4, true);
|
|
169
183
|
const segCountLen = dv.getUint32(8, true);
|
|
170
184
|
const size = dv.getUint32(12, true);
|
|
185
|
+
if (seg === 0 || (seg & seg - 1) !== 0 || seg > 1 << 18) throw new SerializationError(`invalid fuse segment length ${String(seg)}`);
|
|
186
|
+
if (segCountLen % seg !== 0) throw new SerializationError(`fuse segment count length ${String(segCountLen)} is not a multiple of segment length ${String(seg)}`);
|
|
171
187
|
const bpe = expectedType === TYPE_FUSE8 ? 1 : 2;
|
|
172
188
|
const expectedArrayLength = size === 0 ? 0 : segCountLen + 2 * seg;
|
|
173
189
|
assertBodyLength(body.length, 16 + expectedArrayLength * bpe, "fuse");
|
|
@@ -211,6 +227,10 @@ var BinaryFuse = class {
|
|
|
211
227
|
get size() {
|
|
212
228
|
return this.#size;
|
|
213
229
|
}
|
|
230
|
+
/** Hash seed selected during construction (may differ from 0 after a peel retry). */
|
|
231
|
+
get seed() {
|
|
232
|
+
return this.#seed;
|
|
233
|
+
}
|
|
214
234
|
/** Actual bits stored per key (`0` for an empty filter). */
|
|
215
235
|
get bitsPerKey() {
|
|
216
236
|
return this.#size === 0 ? 0 : this.#fp.byteLength * 8 / this.#size;
|
|
@@ -222,18 +242,17 @@ var BinaryFuse = class {
|
|
|
222
242
|
*/
|
|
223
243
|
toBytes() {
|
|
224
244
|
const laneBytes = new Uint8Array(this.#fp.buffer, this.#fp.byteOffset, this.#fp.byteLength);
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
dv.setUint32(0, this.#seed, true);
|
|
228
|
-
dv.setUint32(4, this.#seg, true);
|
|
229
|
-
dv.setUint32(8, this.#segCountLen, true);
|
|
230
|
-
dv.setUint32(12, this.#size, true);
|
|
231
|
-
body.set(laneBytes, 16);
|
|
232
|
-
return writeHeader({
|
|
233
|
-
version: 2,
|
|
245
|
+
return writeFrame({
|
|
246
|
+
version: 3,
|
|
234
247
|
type: this.#fp.BYTES_PER_ELEMENT === 1 ? TYPE_FUSE8 : TYPE_FUSE16,
|
|
235
248
|
flags: 0
|
|
236
|
-
}, body)
|
|
249
|
+
}, 16 + laneBytes.length, (body, dv) => {
|
|
250
|
+
dv.setUint32(0, this.#seed, true);
|
|
251
|
+
dv.setUint32(4, this.#seg, true);
|
|
252
|
+
dv.setUint32(8, this.#segCountLen, true);
|
|
253
|
+
dv.setUint32(12, this.#size, true);
|
|
254
|
+
body.set(laneBytes, 16);
|
|
255
|
+
});
|
|
237
256
|
}
|
|
238
257
|
/**
|
|
239
258
|
* Tests whether a key is in the set.
|
|
@@ -244,7 +263,7 @@ var BinaryFuse = class {
|
|
|
244
263
|
has(key) {
|
|
245
264
|
if (this.#fp.length === 0) return false;
|
|
246
265
|
hash128KeyInto(key, 0, scratchHash);
|
|
247
|
-
mixSeed(scratchHash.
|
|
266
|
+
mixSeed(scratchHash.w0 >>> 0, scratchHash.w1 >>> 0, this.#seed);
|
|
248
267
|
const mlo = RLO;
|
|
249
268
|
const mhi = RHI;
|
|
250
269
|
positionsInto(mlo, mhi, this.#seg, this.#segMask, this.#segCountLen, this.#pos);
|
|
@@ -254,6 +273,26 @@ var BinaryFuse = class {
|
|
|
254
273
|
const p2 = this.#pos[2] ?? 0;
|
|
255
274
|
return ((mlo ^ mhi) & mask) === (((this.#fp[p0] ?? 0) ^ (this.#fp[p1] ?? 0) ^ (this.#fp[p2] ?? 0)) & mask);
|
|
256
275
|
}
|
|
276
|
+
/**
|
|
277
|
+
* Tests structural equality: `true` when `other` serializes to identical
|
|
278
|
+
* bytes. A {@link BinaryFuse8} and a {@link BinaryFuse16} are never equal,
|
|
279
|
+
* since their frames carry different type bytes.
|
|
280
|
+
*
|
|
281
|
+
* @param other - The filter to compare against.
|
|
282
|
+
* @returns `true` if the two filters are byte-for-byte identical.
|
|
283
|
+
*/
|
|
284
|
+
equals(other) {
|
|
285
|
+
return bytesEqual(this.toBytes(), other.toBytes());
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Serializes the filter to a JSON-friendly envelope wrapping the base64 of
|
|
289
|
+
* the `toBytes` frame.
|
|
290
|
+
*
|
|
291
|
+
* @returns The envelope, readable by the matching `fromJSON`.
|
|
292
|
+
*/
|
|
293
|
+
toJSON() {
|
|
294
|
+
return toJSONEnvelope(this.toBytes());
|
|
295
|
+
}
|
|
257
296
|
};
|
|
258
297
|
/**
|
|
259
298
|
* A static 8-bit binary fuse filter: built once from a key set, then immutable.
|
|
@@ -286,6 +325,15 @@ var BinaryFuse8 = class BinaryFuse8 extends BinaryFuse {
|
|
|
286
325
|
static fromBytes(bytes) {
|
|
287
326
|
return new BinaryFuse8(fuseStateFromBytes(bytes, TYPE_FUSE8));
|
|
288
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* Restores a filter from its {@link BinaryFuse8.toJSON} envelope.
|
|
330
|
+
*
|
|
331
|
+
* @param value - The JSON envelope.
|
|
332
|
+
* @returns The reconstructed filter.
|
|
333
|
+
*/
|
|
334
|
+
static fromJSON(value) {
|
|
335
|
+
return BinaryFuse8.fromBytes(fromJSONEnvelope(value));
|
|
336
|
+
}
|
|
289
337
|
};
|
|
290
338
|
/**
|
|
291
339
|
* A static 16-bit binary fuse filter: like {@link BinaryFuse8} but twice the
|
|
@@ -317,6 +365,15 @@ var BinaryFuse16 = class BinaryFuse16 extends BinaryFuse {
|
|
|
317
365
|
static fromBytes(bytes) {
|
|
318
366
|
return new BinaryFuse16(fuseStateFromBytes(bytes, TYPE_FUSE16));
|
|
319
367
|
}
|
|
368
|
+
/**
|
|
369
|
+
* Restores a filter from its {@link BinaryFuse16.toJSON} envelope.
|
|
370
|
+
*
|
|
371
|
+
* @param value - The JSON envelope.
|
|
372
|
+
* @returns The reconstructed filter.
|
|
373
|
+
*/
|
|
374
|
+
static fromJSON(value) {
|
|
375
|
+
return BinaryFuse16.fromBytes(fromJSONEnvelope(value));
|
|
376
|
+
}
|
|
320
377
|
};
|
|
321
378
|
//#endregion
|
|
322
|
-
export { BinaryFuse16, BinaryFuse8, BinaryFuseBuildError };
|
|
379
|
+
export { BinaryFuse16, BinaryFuse8, BinaryFuseBuildError, fuseBitsPerKey };
|
package/dist/index.cjs
CHANGED
package/dist/index.js
CHANGED
|
@@ -12,6 +12,10 @@ function assertPositiveInt(value, label) {
|
|
|
12
12
|
function assertPositiveFinite(value, label) {
|
|
13
13
|
if (!Number.isFinite(value) || value <= 0) throw new ParamError(`${label} must be a positive number, got ${String(value)}`);
|
|
14
14
|
}
|
|
15
|
+
/** Asserts `value` is an integer in the uint16 range `[0, 65535]`. */
|
|
16
|
+
function assertUint16(value, label) {
|
|
17
|
+
if (!Number.isInteger(value) || value < 0 || value > 65535) throw new ParamError(`${label} must be a uint16, got ${String(value)}`);
|
|
18
|
+
}
|
|
15
19
|
/** Asserts `value` is an integer in the uint32 range `[0, 2^32 - 1]`. */
|
|
16
20
|
function assertUint32(value, label) {
|
|
17
21
|
if (!Number.isInteger(value) || value < 0 || value > 4294967295) throw new ParamError(`${label} must be a uint32, got ${String(value)}`);
|
|
@@ -45,6 +49,12 @@ Object.defineProperty(exports, "assertProbability", {
|
|
|
45
49
|
return assertProbability;
|
|
46
50
|
}
|
|
47
51
|
});
|
|
52
|
+
Object.defineProperty(exports, "assertUint16", {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
get: function() {
|
|
55
|
+
return assertUint16;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
48
58
|
Object.defineProperty(exports, "assertUint32", {
|
|
49
59
|
enumerable: true,
|
|
50
60
|
get: function() {
|
|
@@ -12,6 +12,10 @@ function assertPositiveInt(value, label) {
|
|
|
12
12
|
function assertPositiveFinite(value, label) {
|
|
13
13
|
if (!Number.isFinite(value) || value <= 0) throw new ParamError(`${label} must be a positive number, got ${String(value)}`);
|
|
14
14
|
}
|
|
15
|
+
/** Asserts `value` is an integer in the uint16 range `[0, 65535]`. */
|
|
16
|
+
function assertUint16(value, label) {
|
|
17
|
+
if (!Number.isInteger(value) || value < 0 || value > 65535) throw new ParamError(`${label} must be a uint16, got ${String(value)}`);
|
|
18
|
+
}
|
|
15
19
|
/** Asserts `value` is an integer in the uint32 range `[0, 2^32 - 1]`. */
|
|
16
20
|
function assertUint32(value, label) {
|
|
17
21
|
if (!Number.isInteger(value) || value < 0 || value > 4294967295) throw new ParamError(`${label} must be a uint32, got ${String(value)}`);
|
|
@@ -21,4 +25,4 @@ function assertProbability(value, label) {
|
|
|
21
25
|
if (!Number.isFinite(value) || value <= 0 || value >= 1) throw new ParamError(`${label} must be in the open interval (0, 1), got ${String(value)}`);
|
|
22
26
|
}
|
|
23
27
|
//#endregion
|
|
24
|
-
export {
|
|
28
|
+
export { assertUint16 as a, assertProbability as i, assertPositiveFinite as n, assertUint32 as o, assertPositiveInt as r, ParamError as t };
|