distillate 0.8.2 → 0.10.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 +53 -6
- package/dist/blocked/index.cjs +15 -10
- package/dist/blocked/index.d.cts +7 -6
- package/dist/blocked/index.d.ts +7 -6
- package/dist/blocked/index.js +13 -9
- package/dist/bloom/index.cjs +35 -34
- package/dist/bloom/index.d.cts +22 -17
- package/dist/bloom/index.d.ts +22 -17
- package/dist/bloom/index.js +32 -32
- package/dist/bytes-DCuYtUVS.d.cts +4 -0
- package/dist/bytes-DCuYtUVS.d.ts +4 -0
- package/dist/frame/index.cjs +9 -0
- package/dist/frame/index.d.cts +2 -0
- package/dist/frame/index.d.ts +2 -0
- package/dist/frame/index.js +2 -0
- package/dist/fuse/index.cjs +27 -23
- package/dist/fuse/index.d.cts +7 -6
- package/dist/fuse/index.d.ts +7 -6
- package/dist/fuse/index.js +15 -12
- package/dist/hasher-D8LCBTOM.cjs +276 -0
- package/dist/hasher-DVWXS_vJ.js +229 -0
- package/dist/hll/index.cjs +366 -0
- package/dist/hll/index.d.cts +120 -0
- package/dist/hll/index.d.ts +120 -0
- package/dist/hll/index.js +356 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -3
- package/dist/index.d.ts +2 -3
- package/dist/index.js +1 -1
- package/dist/serialize--xR6vGSW.d.cts +112 -0
- package/dist/serialize--xR6vGSW.d.ts +112 -0
- package/dist/serialize-CHikZ4GH.cjs +296 -0
- package/dist/serialize-CMSYFym-.js +201 -0
- package/dist/sizing-BLzZk2zr.cjs +28 -0
- package/dist/sizing-BtUrtvF_.js +17 -0
- package/dist/sizing-wYOW27eY.d.cts +22 -0
- package/dist/sizing-wYOW27eY.d.ts +22 -0
- package/package.json +26 -10
- package/dist/serialize-BqIcsR2J.js +0 -388
- package/dist/serialize-CXnRWItH.cjs +0 -513
- package/dist/serialize-ChyWpB9F.d.cts +0 -73
- package/dist/serialize-ChyWpB9F.d.ts +0 -73
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import { i as hash128KeyInto } from "../hasher-DVWXS_vJ.js";
|
|
2
|
+
import { a as TruncatedError, c as assertBodyLength, f as fromJSONEnvelope, g as writeFrame, h as toJSONEnvelope, i as SerializationError, l as assertMinBodyLength, m as readHeader, n as ChecksumError, o as UnknownHashVariantError, r as ReservedBitsError, s as UnknownVersionError, t as BadMagicError, u as assertParamsPadding } from "../serialize-CMSYFym-.js";
|
|
3
|
+
import { o as assertUint32, t as ParamError } from "../params-CeajSrwv.js";
|
|
4
|
+
import { n as hllSizing } from "../sizing-BtUrtvF_.js";
|
|
5
|
+
//#region src/hll/estimate.ts
|
|
6
|
+
const ALPHA_INF = .5 / Math.LN2;
|
|
7
|
+
function sigma(x) {
|
|
8
|
+
if (x === 1) return Infinity;
|
|
9
|
+
let y = 1;
|
|
10
|
+
let z = x;
|
|
11
|
+
let previous;
|
|
12
|
+
do {
|
|
13
|
+
x *= x;
|
|
14
|
+
previous = z;
|
|
15
|
+
z += x * y;
|
|
16
|
+
y += y;
|
|
17
|
+
} while (z !== previous);
|
|
18
|
+
return z;
|
|
19
|
+
}
|
|
20
|
+
function tau(x) {
|
|
21
|
+
if (x === 0 || x === 1) return 0;
|
|
22
|
+
let y = 1;
|
|
23
|
+
let z = 1 - x;
|
|
24
|
+
let previous;
|
|
25
|
+
do {
|
|
26
|
+
x = Math.sqrt(x);
|
|
27
|
+
previous = z;
|
|
28
|
+
y *= .5;
|
|
29
|
+
const gap = 1 - x;
|
|
30
|
+
z -= gap * gap * y;
|
|
31
|
+
} while (z !== previous);
|
|
32
|
+
return z / 3;
|
|
33
|
+
}
|
|
34
|
+
function estimate(hist, p) {
|
|
35
|
+
const m = 2 ** p;
|
|
36
|
+
const q = 64 - p;
|
|
37
|
+
let z = m * tau((m - (hist[q + 1] ?? 0)) / m);
|
|
38
|
+
for (let k = q; k >= 1; k--) z = .5 * (z + (hist[k] ?? 0));
|
|
39
|
+
z += m * sigma((hist[0] ?? 0) / m);
|
|
40
|
+
return ALPHA_INF * m * m / z;
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/hll/fold.ts
|
|
44
|
+
function foldRho(index, rho, d) {
|
|
45
|
+
const mid = index & (1 << d) - 1;
|
|
46
|
+
if (mid === 0) return d + rho;
|
|
47
|
+
return Math.clz32(mid) - 32 + d + 1;
|
|
48
|
+
}
|
|
49
|
+
function foldDense(src, srcP, dst, dstP) {
|
|
50
|
+
const d = srcP - dstP;
|
|
51
|
+
for (let i = 0; i < 2 ** srcP; i++) {
|
|
52
|
+
const rho = src.get(i);
|
|
53
|
+
if (rho === 0) continue;
|
|
54
|
+
dst.raise(i >>> d, foldRho(i, rho, d));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/hll/registers.ts
|
|
59
|
+
const WIDTH = 6;
|
|
60
|
+
const MASK = 63;
|
|
61
|
+
var Registers = class {
|
|
62
|
+
#bytes;
|
|
63
|
+
constructor(p) {
|
|
64
|
+
this.#bytes = new Uint8Array(WIDTH * 2 ** p / 8);
|
|
65
|
+
}
|
|
66
|
+
get bytes() {
|
|
67
|
+
return this.#bytes;
|
|
68
|
+
}
|
|
69
|
+
max() {
|
|
70
|
+
const bytes = this.#bytes;
|
|
71
|
+
let max = 0;
|
|
72
|
+
for (let at = 0; at < bytes.length; at += 3) {
|
|
73
|
+
const word = (bytes[at] ?? 0) | (bytes[at + 1] ?? 0) << 8 | (bytes[at + 2] ?? 0) << 16;
|
|
74
|
+
const a = word & MASK;
|
|
75
|
+
const b = word >>> 6 & MASK;
|
|
76
|
+
const c = word >>> 12 & MASK;
|
|
77
|
+
const d = word >>> 18 & MASK;
|
|
78
|
+
if (a > max) max = a;
|
|
79
|
+
if (b > max) max = b;
|
|
80
|
+
if (c > max) max = c;
|
|
81
|
+
if (d > max) max = d;
|
|
82
|
+
}
|
|
83
|
+
return max;
|
|
84
|
+
}
|
|
85
|
+
get(i) {
|
|
86
|
+
const bit = i * WIDTH;
|
|
87
|
+
const at = bit >>> 3;
|
|
88
|
+
return ((this.#bytes[at] ?? 0) | (this.#bytes[at + 1] ?? 0) << 8) >>> (bit & 7) & MASK;
|
|
89
|
+
}
|
|
90
|
+
raise(i, v) {
|
|
91
|
+
if (v > this.get(i)) this.set(i, v);
|
|
92
|
+
}
|
|
93
|
+
set(i, v) {
|
|
94
|
+
const bit = i * WIDTH;
|
|
95
|
+
const at = bit >>> 3;
|
|
96
|
+
const off = bit & 7;
|
|
97
|
+
const word = ((this.#bytes[at] ?? 0) | (this.#bytes[at + 1] ?? 0) << 8) & ~(MASK << off) | (v & MASK) << off;
|
|
98
|
+
this.#bytes[at] = word & 255;
|
|
99
|
+
if (at + 1 < this.#bytes.length) this.#bytes[at + 1] = word >>> 8 & 255;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const RHO_BITS = 6;
|
|
103
|
+
const RHO_MASK = 63;
|
|
104
|
+
function encodeSparse(index, rho) {
|
|
105
|
+
return index << RHO_BITS | rho;
|
|
106
|
+
}
|
|
107
|
+
function sparseIndex(entry) {
|
|
108
|
+
return entry >>> RHO_BITS;
|
|
109
|
+
}
|
|
110
|
+
function sparseRho(entry) {
|
|
111
|
+
return entry & RHO_MASK;
|
|
112
|
+
}
|
|
113
|
+
function foldSparse(buf, len, fromP, registers, toP) {
|
|
114
|
+
const d = fromP - toP;
|
|
115
|
+
for (let i = 0; i < len; i++) {
|
|
116
|
+
const entry = buf[i] ?? 0;
|
|
117
|
+
const at = sparseIndex(entry) >>> 25 - fromP;
|
|
118
|
+
registers.raise(at >>> d, foldRho(at, sparseRho(entry), d));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function refoldSparse(entry, fromP, toP) {
|
|
122
|
+
const index = sparseIndex(entry);
|
|
123
|
+
return encodeSparse(index, foldRho(index >>> 25 - fromP, sparseRho(entry), fromP - toP));
|
|
124
|
+
}
|
|
125
|
+
function compact(buf, len) {
|
|
126
|
+
if (len === 0) return 0;
|
|
127
|
+
buf.subarray(0, len).sort();
|
|
128
|
+
let out = 0;
|
|
129
|
+
for (let i = 0; i < len; i++) {
|
|
130
|
+
const entry = buf[i] ?? 0;
|
|
131
|
+
const next = buf[i + 1] ?? 0;
|
|
132
|
+
if (i + 1 < len && sparseIndex(next) === sparseIndex(entry)) continue;
|
|
133
|
+
buf[out++] = entry;
|
|
134
|
+
}
|
|
135
|
+
return out;
|
|
136
|
+
}
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/hll/hll.ts
|
|
139
|
+
const ERROR_CONSTANT = 1.04;
|
|
140
|
+
const TYPE = 5;
|
|
141
|
+
const PARAMS_SIZE = 8;
|
|
142
|
+
const PARAMS_FIELDS_END = 6;
|
|
143
|
+
const DENSE = 0;
|
|
144
|
+
const SPARSE = 1;
|
|
145
|
+
const ENTRY_SIZE = 4;
|
|
146
|
+
function assertPrecision(p) {
|
|
147
|
+
if (!Number.isInteger(p) || p < 4 || p > 18) throw new ParamError(`p must be an integer in [${String(4)}, ${String(18)}], got ${String(p)}`);
|
|
148
|
+
}
|
|
149
|
+
function sparseCapacity(registers) {
|
|
150
|
+
return registers.bytes.length >> 2;
|
|
151
|
+
}
|
|
152
|
+
var HyperLogLog = class HyperLogLog {
|
|
153
|
+
#registers;
|
|
154
|
+
#p;
|
|
155
|
+
#seed;
|
|
156
|
+
#scratch = {
|
|
157
|
+
w0: 0,
|
|
158
|
+
w1: 0,
|
|
159
|
+
w2: 0,
|
|
160
|
+
w3: 0
|
|
161
|
+
};
|
|
162
|
+
#sparse;
|
|
163
|
+
#len = 0;
|
|
164
|
+
constructor({ p, seed = 0 }) {
|
|
165
|
+
assertPrecision(p);
|
|
166
|
+
assertUint32(seed, "seed");
|
|
167
|
+
this.#registers = new Registers(p);
|
|
168
|
+
this.#p = p;
|
|
169
|
+
this.#seed = seed;
|
|
170
|
+
this.#sparse = new Int32Array(sparseCapacity(this.#registers));
|
|
171
|
+
}
|
|
172
|
+
static create(relativeError) {
|
|
173
|
+
return new HyperLogLog(hllSizing(relativeError));
|
|
174
|
+
}
|
|
175
|
+
static from(keys, relativeError) {
|
|
176
|
+
const sketch = HyperLogLog.create(relativeError);
|
|
177
|
+
for (const key of keys) sketch.add(key);
|
|
178
|
+
return sketch;
|
|
179
|
+
}
|
|
180
|
+
static fromBytes(bytes) {
|
|
181
|
+
const { type, flags, body } = readHeader(bytes);
|
|
182
|
+
if (type !== TYPE) throw new SerializationError(`expected DSTL type ${String(TYPE)}, got ${String(type)}`);
|
|
183
|
+
if ((flags & 15) !== 0) throw new UnknownHashVariantError(`unsupported hash variant ${String(flags & 15)}`);
|
|
184
|
+
assertMinBodyLength(body.length, PARAMS_SIZE, "hll");
|
|
185
|
+
assertParamsPadding(body, PARAMS_FIELDS_END, PARAMS_SIZE, "hll");
|
|
186
|
+
const dv = new DataView(body.buffer, body.byteOffset, body.byteLength);
|
|
187
|
+
const p = body[0] ?? 0;
|
|
188
|
+
const encoding = body[1] ?? 0;
|
|
189
|
+
const seed = dv.getUint32(2, true);
|
|
190
|
+
if (encoding !== DENSE && encoding !== SPARSE) throw new SerializationError(`unknown hll encoding ${String(encoding)}`);
|
|
191
|
+
const sketch = new HyperLogLog({
|
|
192
|
+
p,
|
|
193
|
+
seed
|
|
194
|
+
});
|
|
195
|
+
const payload = body.length - PARAMS_SIZE;
|
|
196
|
+
const maxRho = 65 - p;
|
|
197
|
+
if (encoding === DENSE) {
|
|
198
|
+
assertBodyLength(body.length, PARAMS_SIZE + sketch.#registers.bytes.length, "hll");
|
|
199
|
+
sketch.#goDense();
|
|
200
|
+
sketch.#registers.bytes.set(body.subarray(PARAMS_SIZE));
|
|
201
|
+
const largest = sketch.#registers.max();
|
|
202
|
+
if (largest > maxRho) throw new SerializationError(`hll: register holds ${String(largest)}, above the maximum ${String(maxRho)} at p ${String(p)}`);
|
|
203
|
+
return sketch;
|
|
204
|
+
}
|
|
205
|
+
const capacity = sparseCapacity(sketch.#registers);
|
|
206
|
+
if (payload % ENTRY_SIZE !== 0 || payload / ENTRY_SIZE > capacity) throw new TruncatedError(`hll: sparse payload of ${String(payload)} bytes is not up to ${String(capacity)} whole entries`);
|
|
207
|
+
const entries = payload / ENTRY_SIZE;
|
|
208
|
+
const buffer = new Int32Array(capacity);
|
|
209
|
+
for (let i = 0; i < entries; i++) {
|
|
210
|
+
const entry = dv.getUint32(PARAMS_SIZE + i * ENTRY_SIZE, true);
|
|
211
|
+
if (entry > 2147483647) throw new SerializationError(`hll: sparse entry ${String(entry)} does not fit the 31-bit encoding`);
|
|
212
|
+
const rho = sparseRho(entry);
|
|
213
|
+
if (rho > maxRho) throw new SerializationError(`hll: sparse entry holds rho ${String(rho)}, above the maximum ${String(maxRho)} at p ${String(p)}`);
|
|
214
|
+
buffer[i] = entry;
|
|
215
|
+
}
|
|
216
|
+
sketch.#sparse = buffer;
|
|
217
|
+
sketch.#len = entries;
|
|
218
|
+
return sketch;
|
|
219
|
+
}
|
|
220
|
+
toBytes() {
|
|
221
|
+
const sparse = this.#sparse;
|
|
222
|
+
if (sparse !== null) {
|
|
223
|
+
const entries = compact(sparse, this.#len);
|
|
224
|
+
this.#len = entries;
|
|
225
|
+
return writeFrame({
|
|
226
|
+
version: 5,
|
|
227
|
+
type: TYPE,
|
|
228
|
+
flags: 0
|
|
229
|
+
}, PARAMS_SIZE, entries * ENTRY_SIZE, (body, dv) => {
|
|
230
|
+
body[0] = this.#p;
|
|
231
|
+
body[1] = SPARSE;
|
|
232
|
+
dv.setUint32(2, this.#seed, true);
|
|
233
|
+
for (let i = 0; i < entries; i++) dv.setUint32(PARAMS_SIZE + i * ENTRY_SIZE, sparse[i] ?? 0, true);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
const payload = this.#registers.bytes;
|
|
237
|
+
return writeFrame({
|
|
238
|
+
version: 5,
|
|
239
|
+
type: TYPE,
|
|
240
|
+
flags: 0
|
|
241
|
+
}, PARAMS_SIZE, payload.length, (body, dv) => {
|
|
242
|
+
body[0] = this.#p;
|
|
243
|
+
body[1] = DENSE;
|
|
244
|
+
dv.setUint32(2, this.#seed, true);
|
|
245
|
+
body.set(payload, PARAMS_SIZE);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
toJSON() {
|
|
249
|
+
return toJSONEnvelope(this.toBytes());
|
|
250
|
+
}
|
|
251
|
+
static fromJSON(value) {
|
|
252
|
+
return HyperLogLog.fromBytes(fromJSONEnvelope(value));
|
|
253
|
+
}
|
|
254
|
+
get p() {
|
|
255
|
+
return this.#p;
|
|
256
|
+
}
|
|
257
|
+
get seed() {
|
|
258
|
+
return this.#seed;
|
|
259
|
+
}
|
|
260
|
+
get standardError() {
|
|
261
|
+
return ERROR_CONSTANT / Math.sqrt(2 ** this.#p);
|
|
262
|
+
}
|
|
263
|
+
add(key) {
|
|
264
|
+
const s = this.#scratch;
|
|
265
|
+
hash128KeyInto(key, this.#seed, s);
|
|
266
|
+
const p = this.#p;
|
|
267
|
+
const tail = s.w0 << p >>> 0;
|
|
268
|
+
const rho = tail !== 0 ? Math.clz32(tail) + 1 : 32 - p + Math.clz32(s.w1) + 1;
|
|
269
|
+
const sparse = this.#sparse;
|
|
270
|
+
if (sparse === null) {
|
|
271
|
+
this.#registers.raise(s.w0 >>> 32 - p, rho);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
sparse[this.#len++] = encodeSparse(s.w0 >>> 7, rho);
|
|
275
|
+
if (this.#len === sparse.length) this.#collapse(sparse);
|
|
276
|
+
}
|
|
277
|
+
#collapse(sparse) {
|
|
278
|
+
const distinct = compact(sparse, this.#len);
|
|
279
|
+
this.#len = distinct;
|
|
280
|
+
const slack = Math.max(1, sparse.length >> 2);
|
|
281
|
+
if (distinct > sparse.length - slack) this.#goDense();
|
|
282
|
+
}
|
|
283
|
+
union(other) {
|
|
284
|
+
if (other.#seed !== this.#seed) throw new ParamError(`cannot merge sketches with different seeds, got ${String(this.#seed)} and ${String(other.#seed)}`);
|
|
285
|
+
const p = Math.min(this.#p, other.#p);
|
|
286
|
+
const merged = new HyperLogLog({
|
|
287
|
+
p,
|
|
288
|
+
seed: this.#seed
|
|
289
|
+
});
|
|
290
|
+
merged.#drain(this);
|
|
291
|
+
merged.#drain(other);
|
|
292
|
+
return merged;
|
|
293
|
+
}
|
|
294
|
+
#drain(src) {
|
|
295
|
+
const sparse = src.#sparse;
|
|
296
|
+
if (sparse === null) {
|
|
297
|
+
this.#goDense();
|
|
298
|
+
foldDense(src.#registers, src.#p, this.#registers, this.#p);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
const distinct = compact(sparse, src.#len);
|
|
302
|
+
src.#len = distinct;
|
|
303
|
+
for (let i = 0; i < distinct; i++) this.#absorb(refoldSparse(sparse[i] ?? 0, src.#p, this.#p));
|
|
304
|
+
}
|
|
305
|
+
#absorb(entry) {
|
|
306
|
+
const sparse = this.#sparse;
|
|
307
|
+
if (sparse === null) {
|
|
308
|
+
const index = sparseIndex(entry) >>> 25 - this.#p;
|
|
309
|
+
this.#registers.raise(index, sparseRho(entry));
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
sparse[this.#len++] = entry;
|
|
313
|
+
if (this.#len === sparse.length) this.#collapse(sparse);
|
|
314
|
+
}
|
|
315
|
+
#goDense() {
|
|
316
|
+
const sparse = this.#sparse;
|
|
317
|
+
if (sparse === null) return;
|
|
318
|
+
foldSparse(sparse, this.#len, this.#p, this.#registers, this.#p);
|
|
319
|
+
this.#sparse = null;
|
|
320
|
+
this.#len = 0;
|
|
321
|
+
}
|
|
322
|
+
#dense() {
|
|
323
|
+
const sparse = this.#sparse;
|
|
324
|
+
if (sparse === null) return this.#registers;
|
|
325
|
+
const out = new Registers(this.#p);
|
|
326
|
+
foldSparse(sparse, this.#len, this.#p, out, this.#p);
|
|
327
|
+
return out;
|
|
328
|
+
}
|
|
329
|
+
equals(other) {
|
|
330
|
+
if (other.#p !== this.#p || other.#seed !== this.#seed) return false;
|
|
331
|
+
const mine = this.#dense().bytes;
|
|
332
|
+
const theirs = other.#dense().bytes;
|
|
333
|
+
for (let i = 0; i < mine.length; i++) if (mine[i] !== theirs[i]) return false;
|
|
334
|
+
return true;
|
|
335
|
+
}
|
|
336
|
+
count() {
|
|
337
|
+
const sparse = this.#sparse;
|
|
338
|
+
if (sparse !== null) {
|
|
339
|
+
const distinct = compact(sparse, this.#len);
|
|
340
|
+
this.#len = distinct;
|
|
341
|
+
const buckets = 2 ** 25;
|
|
342
|
+
return Math.round(buckets * Math.log(buckets / (buckets - distinct)));
|
|
343
|
+
}
|
|
344
|
+
const p = this.#p;
|
|
345
|
+
const q = 64 - p;
|
|
346
|
+
const m = 2 ** p;
|
|
347
|
+
const hist = new Int32Array(q + 2);
|
|
348
|
+
for (let i = 0; i < m; i++) {
|
|
349
|
+
const value = this.#registers.get(i);
|
|
350
|
+
hist[value] = (hist[value] ?? 0) + 1;
|
|
351
|
+
}
|
|
352
|
+
return Math.round(estimate(hist, p));
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
//#endregion
|
|
356
|
+
export { BadMagicError, ChecksumError, HyperLogLog, ParamError, ReservedBitsError, SerializationError, TruncatedError, UnknownHashVariantError, UnknownVersionError, hllSizing };
|
package/dist/index.cjs
CHANGED
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
//#region src/core/serialize.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Base class for every defect `fromBytes` and `fromJSON` reject. Thrown
|
|
4
|
+
* directly when a JSON envelope is malformed: not an object, missing the
|
|
5
|
+
* `"distillate"` tag, missing `data`, or `data` that is not valid base64.
|
|
6
|
+
* Catch this to handle any decode failure at once, or a subclass to tell the
|
|
7
|
+
* causes apart. The input is corrupt or foreign, so discard it; retrying the
|
|
8
|
+
* same bytes cannot succeed.
|
|
9
|
+
*/
|
|
10
|
+
declare class SerializationError extends Error {
|
|
11
|
+
/** Discriminates this error from other `Error`s. */
|
|
12
|
+
override readonly name: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Thrown when a frame is shorter than its header plus trailer, when the body
|
|
16
|
+
* length its header declares disagrees with the bytes actually present, or
|
|
17
|
+
* when its body length does not match the length its declared params imply.
|
|
18
|
+
* The bytes were cut short in transit or storage; re-fetch the whole frame.
|
|
19
|
+
*/
|
|
20
|
+
declare class TruncatedError extends SerializationError {
|
|
21
|
+
/** Discriminates this error from other `Error`s. */
|
|
22
|
+
override readonly name = "TruncatedError";
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Thrown when a frame does not start with the four-byte `DSTL` magic, so it
|
|
26
|
+
* was never produced by `toBytes`. Frames written before format version 4
|
|
27
|
+
* carry the older `AMQF` magic and are rejected here; re-serialize them with
|
|
28
|
+
* the version you run. Otherwise check that the bytes really are a distillate
|
|
29
|
+
* frame and not another payload, a text encoding of one, or a slice taken at
|
|
30
|
+
* the wrong offset.
|
|
31
|
+
*/
|
|
32
|
+
declare class BadMagicError extends SerializationError {
|
|
33
|
+
/** Discriminates this error from other `Error`s. */
|
|
34
|
+
override readonly name = "BadMagicError";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Thrown when a frame or JSON envelope declares a format version this release
|
|
38
|
+
* does not read. The remedy depends on which side is older. A frame newer than
|
|
39
|
+
* this release needs `distillate` upgraded on the reading side. A frame older
|
|
40
|
+
* than it is readable by no current release, since each reads exactly one
|
|
41
|
+
* format version; rebuild it from the source keys. Being at least as new as
|
|
42
|
+
* the producer is necessary, not sufficient.
|
|
43
|
+
*/
|
|
44
|
+
declare class UnknownVersionError extends SerializationError {
|
|
45
|
+
/** Discriminates this error from other `Error`s. */
|
|
46
|
+
override readonly name = "UnknownVersionError";
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Thrown when a frame's flags nibble names a hash or index mapping this
|
|
50
|
+
* release cannot reproduce, so its stored bits are unreadable. Rebuild the filter from the
|
|
51
|
+
* source keys with the version you run.
|
|
52
|
+
*/
|
|
53
|
+
declare class UnknownHashVariantError extends SerializationError {
|
|
54
|
+
/** Discriminates this error from other `Error`s. */
|
|
55
|
+
override readonly name = "UnknownHashVariantError";
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Thrown when a frame sets a header bit this format reserves: the flags high
|
|
59
|
+
* nibble, the byte at offset 7, or the word at offset 12. Only a newer writer
|
|
60
|
+
* puts anything there, and reading its frame under this release's meaning
|
|
61
|
+
* would give a wrong answer with no error. Upgrade `distillate` on the reading
|
|
62
|
+
* side; a reader must be at least as new as the producer.
|
|
63
|
+
*/
|
|
64
|
+
declare class ReservedBitsError extends SerializationError {
|
|
65
|
+
/** Discriminates this error from other `Error`s. */
|
|
66
|
+
override readonly name = "ReservedBitsError";
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Thrown when a frame's CRC32 trailer does not match its contents, so the
|
|
70
|
+
* bytes were corrupted after they were written. Discard them and re-fetch;
|
|
71
|
+
* the payload cannot be trusted even where it still parses.
|
|
72
|
+
*/
|
|
73
|
+
declare class ChecksumError extends SerializationError {
|
|
74
|
+
/** Discriminates this error from other `Error`s. */
|
|
75
|
+
override readonly name = "ChecksumError";
|
|
76
|
+
}
|
|
77
|
+
/** JSON-friendly envelope for a filter: the binary frame, base64-encoded. */
|
|
78
|
+
interface FilterJSON {
|
|
79
|
+
/** Format tag; always `"distillate"`. */
|
|
80
|
+
$: string;
|
|
81
|
+
/** Binary format version. */
|
|
82
|
+
v: number;
|
|
83
|
+
/** Base64 of the `toBytes` frame. */
|
|
84
|
+
data: string;
|
|
85
|
+
}
|
|
86
|
+
/** One frame read in place from a larger buffer by {@link readFrameAt}. */
|
|
87
|
+
interface Frame {
|
|
88
|
+
/** Binary format version. */
|
|
89
|
+
version: number;
|
|
90
|
+
/** Structure type code; one this release does not implement still reads. */
|
|
91
|
+
type: number;
|
|
92
|
+
/** Header flags byte; the low nibble is the hash variant. */
|
|
93
|
+
flags: number;
|
|
94
|
+
/** The body, a view into the source buffer rather than a copy. */
|
|
95
|
+
body: Uint8Array;
|
|
96
|
+
/** Bytes the whole frame occupies, so `offset + byteLength` is the next one. */
|
|
97
|
+
byteLength: number;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Reads and validates the frame starting at `offset` in `bytes`, which may
|
|
101
|
+
* hold further frames after it: magic, version, declared length, CRC32 and
|
|
102
|
+
* reserved bits, without needing to know the structure type. Advance by the
|
|
103
|
+
* returned `byteLength` to walk a buffer of concatenated frames.
|
|
104
|
+
*
|
|
105
|
+
* @throws TruncatedError when the frame runs past the end of `bytes`.
|
|
106
|
+
* @throws BadMagicError, UnknownVersionError, ChecksumError or
|
|
107
|
+
* ReservedBitsError when the frame at `offset` is not one this release reads.
|
|
108
|
+
* @throws RangeError when `offset` is not a non-negative integer.
|
|
109
|
+
*/
|
|
110
|
+
declare function readFrameAt(bytes: Uint8Array, offset: number): Frame;
|
|
111
|
+
//#endregion
|
|
112
|
+
export { ReservedBitsError as a, UnknownHashVariantError as c, Frame as i, UnknownVersionError as l, ChecksumError as n, SerializationError as o, FilterJSON as r, TruncatedError as s, BadMagicError as t, readFrameAt as u };
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
//#region src/core/serialize.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Base class for every defect `fromBytes` and `fromJSON` reject. Thrown
|
|
4
|
+
* directly when a JSON envelope is malformed: not an object, missing the
|
|
5
|
+
* `"distillate"` tag, missing `data`, or `data` that is not valid base64.
|
|
6
|
+
* Catch this to handle any decode failure at once, or a subclass to tell the
|
|
7
|
+
* causes apart. The input is corrupt or foreign, so discard it; retrying the
|
|
8
|
+
* same bytes cannot succeed.
|
|
9
|
+
*/
|
|
10
|
+
declare class SerializationError extends Error {
|
|
11
|
+
/** Discriminates this error from other `Error`s. */
|
|
12
|
+
override readonly name: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Thrown when a frame is shorter than its header plus trailer, when the body
|
|
16
|
+
* length its header declares disagrees with the bytes actually present, or
|
|
17
|
+
* when its body length does not match the length its declared params imply.
|
|
18
|
+
* The bytes were cut short in transit or storage; re-fetch the whole frame.
|
|
19
|
+
*/
|
|
20
|
+
declare class TruncatedError extends SerializationError {
|
|
21
|
+
/** Discriminates this error from other `Error`s. */
|
|
22
|
+
override readonly name = "TruncatedError";
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Thrown when a frame does not start with the four-byte `DSTL` magic, so it
|
|
26
|
+
* was never produced by `toBytes`. Frames written before format version 4
|
|
27
|
+
* carry the older `AMQF` magic and are rejected here; re-serialize them with
|
|
28
|
+
* the version you run. Otherwise check that the bytes really are a distillate
|
|
29
|
+
* frame and not another payload, a text encoding of one, or a slice taken at
|
|
30
|
+
* the wrong offset.
|
|
31
|
+
*/
|
|
32
|
+
declare class BadMagicError extends SerializationError {
|
|
33
|
+
/** Discriminates this error from other `Error`s. */
|
|
34
|
+
override readonly name = "BadMagicError";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Thrown when a frame or JSON envelope declares a format version this release
|
|
38
|
+
* does not read. The remedy depends on which side is older. A frame newer than
|
|
39
|
+
* this release needs `distillate` upgraded on the reading side. A frame older
|
|
40
|
+
* than it is readable by no current release, since each reads exactly one
|
|
41
|
+
* format version; rebuild it from the source keys. Being at least as new as
|
|
42
|
+
* the producer is necessary, not sufficient.
|
|
43
|
+
*/
|
|
44
|
+
declare class UnknownVersionError extends SerializationError {
|
|
45
|
+
/** Discriminates this error from other `Error`s. */
|
|
46
|
+
override readonly name = "UnknownVersionError";
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Thrown when a frame's flags nibble names a hash or index mapping this
|
|
50
|
+
* release cannot reproduce, so its stored bits are unreadable. Rebuild the filter from the
|
|
51
|
+
* source keys with the version you run.
|
|
52
|
+
*/
|
|
53
|
+
declare class UnknownHashVariantError extends SerializationError {
|
|
54
|
+
/** Discriminates this error from other `Error`s. */
|
|
55
|
+
override readonly name = "UnknownHashVariantError";
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Thrown when a frame sets a header bit this format reserves: the flags high
|
|
59
|
+
* nibble, the byte at offset 7, or the word at offset 12. Only a newer writer
|
|
60
|
+
* puts anything there, and reading its frame under this release's meaning
|
|
61
|
+
* would give a wrong answer with no error. Upgrade `distillate` on the reading
|
|
62
|
+
* side; a reader must be at least as new as the producer.
|
|
63
|
+
*/
|
|
64
|
+
declare class ReservedBitsError extends SerializationError {
|
|
65
|
+
/** Discriminates this error from other `Error`s. */
|
|
66
|
+
override readonly name = "ReservedBitsError";
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Thrown when a frame's CRC32 trailer does not match its contents, so the
|
|
70
|
+
* bytes were corrupted after they were written. Discard them and re-fetch;
|
|
71
|
+
* the payload cannot be trusted even where it still parses.
|
|
72
|
+
*/
|
|
73
|
+
declare class ChecksumError extends SerializationError {
|
|
74
|
+
/** Discriminates this error from other `Error`s. */
|
|
75
|
+
override readonly name = "ChecksumError";
|
|
76
|
+
}
|
|
77
|
+
/** JSON-friendly envelope for a filter: the binary frame, base64-encoded. */
|
|
78
|
+
interface FilterJSON {
|
|
79
|
+
/** Format tag; always `"distillate"`. */
|
|
80
|
+
$: string;
|
|
81
|
+
/** Binary format version. */
|
|
82
|
+
v: number;
|
|
83
|
+
/** Base64 of the `toBytes` frame. */
|
|
84
|
+
data: string;
|
|
85
|
+
}
|
|
86
|
+
/** One frame read in place from a larger buffer by {@link readFrameAt}. */
|
|
87
|
+
interface Frame {
|
|
88
|
+
/** Binary format version. */
|
|
89
|
+
version: number;
|
|
90
|
+
/** Structure type code; one this release does not implement still reads. */
|
|
91
|
+
type: number;
|
|
92
|
+
/** Header flags byte; the low nibble is the hash variant. */
|
|
93
|
+
flags: number;
|
|
94
|
+
/** The body, a view into the source buffer rather than a copy. */
|
|
95
|
+
body: Uint8Array;
|
|
96
|
+
/** Bytes the whole frame occupies, so `offset + byteLength` is the next one. */
|
|
97
|
+
byteLength: number;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Reads and validates the frame starting at `offset` in `bytes`, which may
|
|
101
|
+
* hold further frames after it: magic, version, declared length, CRC32 and
|
|
102
|
+
* reserved bits, without needing to know the structure type. Advance by the
|
|
103
|
+
* returned `byteLength` to walk a buffer of concatenated frames.
|
|
104
|
+
*
|
|
105
|
+
* @throws TruncatedError when the frame runs past the end of `bytes`.
|
|
106
|
+
* @throws BadMagicError, UnknownVersionError, ChecksumError or
|
|
107
|
+
* ReservedBitsError when the frame at `offset` is not one this release reads.
|
|
108
|
+
* @throws RangeError when `offset` is not a non-negative integer.
|
|
109
|
+
*/
|
|
110
|
+
declare function readFrameAt(bytes: Uint8Array, offset: number): Frame;
|
|
111
|
+
//#endregion
|
|
112
|
+
export { ReservedBitsError as a, UnknownHashVariantError as c, Frame as i, UnknownVersionError as l, ChecksumError as n, SerializationError as o, FilterJSON as r, TruncatedError as s, BadMagicError as t, readFrameAt as u };
|