distillate 0.9.0 → 0.11.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 +44 -6
- package/dist/bitset-Cf2jwRJX.js +32 -0
- package/dist/bitset-QYGqxnEf.cjs +37 -0
- package/dist/blocked/index.cjs +14 -9
- package/dist/blocked/index.d.cts +7 -6
- package/dist/blocked/index.d.ts +7 -6
- package/dist/blocked/index.js +12 -8
- package/dist/bloom/index.cjs +16 -41
- package/dist/bloom/index.d.cts +5 -4
- package/dist/bloom/index.d.ts +5 -4
- package/dist/bloom/index.js +13 -39
- 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 +26 -22
- package/dist/fuse/index.d.cts +7 -6
- package/dist/fuse/index.d.ts +7 -6
- package/dist/fuse/index.js +14 -11
- package/dist/hasher-3Cyn7Yg-.js +230 -0
- package/dist/hasher-MhY7aQ8F.cjs +289 -0
- package/dist/hll/index.cjs +12 -8
- package/dist/hll/index.d.cts +4 -3
- package/dist/hll/index.d.ts +4 -3
- package/dist/hll/index.js +11 -8
- 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/scalable/index.cjs +340 -0
- package/dist/scalable/index.d.cts +173 -0
- package/dist/scalable/index.d.ts +173 -0
- package/dist/scalable/index.js +330 -0
- package/dist/{serialize-Bv1zWzrh.d.cts → serialize--xR6vGSW.d.cts} +44 -8
- package/dist/{serialize-Bv1zWzrh.d.ts → serialize--xR6vGSW.d.ts} +44 -8
- package/dist/serialize-CHikZ4GH.cjs +296 -0
- package/dist/serialize-CMSYFym-.js +201 -0
- package/package.json +25 -9
- package/dist/serialize-D59Ri81a.js +0 -392
- package/dist/serialize-Ul2LKFJU.cjs +0 -517
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import { t as BitSet } from "../bitset-Cf2jwRJX.js";
|
|
2
|
+
import { i as hash128KeyInto, l as probeLanesInto, s as probeAt } from "../hasher-3Cyn7Yg-.js";
|
|
3
|
+
import { a as TruncatedError, c as assertBodyLength, d as bytesEqual, 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";
|
|
4
|
+
import { i as assertProbability, o as assertUint32, r as assertPositiveInt, t as ParamError } from "../params-CeajSrwv.js";
|
|
5
|
+
import { t as bloomSizing } from "../sizing-BtUrtvF_.js";
|
|
6
|
+
//#region src/scalable/scalable.ts
|
|
7
|
+
const MAX_BITS = 4294967295;
|
|
8
|
+
const TYPE = 6;
|
|
9
|
+
const PARAMS_SIZE = 40;
|
|
10
|
+
const ENTRY_SIZE = 16;
|
|
11
|
+
const padded8 = (bytes) => Math.ceil(bytes / 8) * 8;
|
|
12
|
+
let restoring;
|
|
13
|
+
var ScalableParamMismatchError = class extends Error {
|
|
14
|
+
name = "ScalableParamMismatchError";
|
|
15
|
+
};
|
|
16
|
+
function readTable(view, stageCount) {
|
|
17
|
+
const entries = [];
|
|
18
|
+
for (let i = 0; i < stageCount; i++) {
|
|
19
|
+
const at = PARAMS_SIZE + ENTRY_SIZE * i;
|
|
20
|
+
const entry = {
|
|
21
|
+
m: view.getUint32(at, true),
|
|
22
|
+
k: view.getUint16(at + 4, true),
|
|
23
|
+
capacity: view.getUint32(at + 8, true),
|
|
24
|
+
count: view.getUint32(at + 12, true)
|
|
25
|
+
};
|
|
26
|
+
if (view.getUint16(at + 6, true) !== 0) throw new SerializationError(`scalable: stage ${String(i)} table padding is not zero`);
|
|
27
|
+
if (entry.m === 0 || entry.k === 0 || entry.capacity === 0) throw new SerializationError(`scalable: stage ${String(i)} declares m=${String(entry.m)}, k=${String(entry.k)}, capacity=${String(entry.capacity)}; all must be positive`);
|
|
28
|
+
if (entry.count > entry.capacity) throw new SerializationError(`scalable: stage ${String(i)} holds ${String(entry.count)} keys, above its capacity of ${String(entry.capacity)}`);
|
|
29
|
+
entries.push(entry);
|
|
30
|
+
}
|
|
31
|
+
return entries;
|
|
32
|
+
}
|
|
33
|
+
function readStages(body, entries, start) {
|
|
34
|
+
let at = start;
|
|
35
|
+
return entries.map((entry, i) => {
|
|
36
|
+
const length = Math.ceil(entry.m / 8);
|
|
37
|
+
const bits = new BitSet(entry.m);
|
|
38
|
+
bits.bytes.set(body.subarray(at, at + length));
|
|
39
|
+
for (let j = at + length; j < at + padded8(length); j++) if (body[j] !== 0) throw new SerializationError(`scalable: stage ${String(i)} bit padding is not zero`);
|
|
40
|
+
at += padded8(length);
|
|
41
|
+
return {
|
|
42
|
+
...entry,
|
|
43
|
+
bits
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
var ScalableBloomFilter = class ScalableBloomFilter {
|
|
48
|
+
#n;
|
|
49
|
+
#epsilon;
|
|
50
|
+
#growth;
|
|
51
|
+
#tightening;
|
|
52
|
+
#seed;
|
|
53
|
+
#stages = [];
|
|
54
|
+
#hash = {
|
|
55
|
+
w0: 0,
|
|
56
|
+
w1: 0,
|
|
57
|
+
w2: 0,
|
|
58
|
+
w3: 0
|
|
59
|
+
};
|
|
60
|
+
#probes = new Uint32Array(0);
|
|
61
|
+
#newest;
|
|
62
|
+
static create(n, epsilon, options = {}) {
|
|
63
|
+
return new ScalableBloomFilter({
|
|
64
|
+
...options,
|
|
65
|
+
n,
|
|
66
|
+
epsilon
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
static from(keys, epsilon, options = {}) {
|
|
70
|
+
const arr = [...keys];
|
|
71
|
+
const f = ScalableBloomFilter.create(Math.max(1, arr.length), epsilon, options);
|
|
72
|
+
for (const key of arr) f.add(key);
|
|
73
|
+
return f;
|
|
74
|
+
}
|
|
75
|
+
constructor({ n, epsilon, growth = 2, tightening = .85, seed = 0 }) {
|
|
76
|
+
assertPositiveInt(n, "n");
|
|
77
|
+
assertUint32(n, "n");
|
|
78
|
+
assertProbability(epsilon, "epsilon");
|
|
79
|
+
if (!Number.isFinite(growth) || growth <= 1) throw new ParamError(`growth must be a finite number greater than 1, got ${String(growth)}`);
|
|
80
|
+
assertProbability(tightening, "tightening");
|
|
81
|
+
assertUint32(seed, "seed");
|
|
82
|
+
this.#n = n;
|
|
83
|
+
this.#epsilon = epsilon;
|
|
84
|
+
this.#growth = growth;
|
|
85
|
+
this.#tightening = tightening;
|
|
86
|
+
this.#seed = seed;
|
|
87
|
+
if (restoring) {
|
|
88
|
+
this.#newest = this.#adopt(restoring);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const first = this.#geometry(0);
|
|
92
|
+
if (first.m > MAX_BITS) throw new ParamError(`the first stage needs ${String(first.m)} bits, more than ${String(MAX_BITS)}`);
|
|
93
|
+
this.#newest = this.#open(first);
|
|
94
|
+
}
|
|
95
|
+
#geometry(i) {
|
|
96
|
+
const capacity = Math.ceil(this.#n * this.#growth ** i);
|
|
97
|
+
const target = this.#epsilon * (1 - this.#tightening) * this.#tightening ** i;
|
|
98
|
+
return {
|
|
99
|
+
capacity,
|
|
100
|
+
...bloomSizing(capacity, target)
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
#open({ capacity, m, k }) {
|
|
104
|
+
const stage = {
|
|
105
|
+
bits: new BitSet(m),
|
|
106
|
+
m,
|
|
107
|
+
k,
|
|
108
|
+
capacity,
|
|
109
|
+
count: 0
|
|
110
|
+
};
|
|
111
|
+
this.#stages.push(stage);
|
|
112
|
+
if (k > this.#probes.length) this.#probes = new Uint32Array(k);
|
|
113
|
+
return stage;
|
|
114
|
+
}
|
|
115
|
+
#settingPairs(other) {
|
|
116
|
+
return [
|
|
117
|
+
[
|
|
118
|
+
"n",
|
|
119
|
+
this.#n,
|
|
120
|
+
other.#n
|
|
121
|
+
],
|
|
122
|
+
[
|
|
123
|
+
"epsilon",
|
|
124
|
+
this.#epsilon,
|
|
125
|
+
other.#epsilon
|
|
126
|
+
],
|
|
127
|
+
[
|
|
128
|
+
"growth",
|
|
129
|
+
this.#growth,
|
|
130
|
+
other.#growth
|
|
131
|
+
],
|
|
132
|
+
[
|
|
133
|
+
"tightening",
|
|
134
|
+
this.#tightening,
|
|
135
|
+
other.#tightening
|
|
136
|
+
],
|
|
137
|
+
[
|
|
138
|
+
"seed",
|
|
139
|
+
this.#seed,
|
|
140
|
+
other.#seed
|
|
141
|
+
]
|
|
142
|
+
];
|
|
143
|
+
}
|
|
144
|
+
#assertMergeable(other) {
|
|
145
|
+
for (const [name, a, b] of this.#settingPairs(other)) if (a !== b) throw new ScalableParamMismatchError(`cannot union scalable Bloom filters whose ${name} differs (${String(a)} vs ${String(b)})`);
|
|
146
|
+
this.#stages.forEach((s, i) => {
|
|
147
|
+
const t = other.#stages[i];
|
|
148
|
+
if (!t) return;
|
|
149
|
+
for (const field of [
|
|
150
|
+
"m",
|
|
151
|
+
"k",
|
|
152
|
+
"capacity"
|
|
153
|
+
]) if (s[field] !== t[field]) throw new ScalableParamMismatchError(`cannot union scalable Bloom filters whose stage ${String(i)} ${field} differs (${String(s[field])} vs ${String(t[field])})`);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
#adopt(stages) {
|
|
157
|
+
this.#stages.length = 0;
|
|
158
|
+
this.#stages.push(...stages);
|
|
159
|
+
const k = Math.max(...stages.map((s) => s.k));
|
|
160
|
+
if (k > this.#probes.length) this.#probes = new Uint32Array(k);
|
|
161
|
+
return stages.reduce((_, s) => s);
|
|
162
|
+
}
|
|
163
|
+
#probe(stage) {
|
|
164
|
+
probeLanesInto(this.#hash.w0, this.#hash.w1, stage.k, stage.m, this.#probes);
|
|
165
|
+
}
|
|
166
|
+
#holds(stage) {
|
|
167
|
+
const { w0, w1 } = this.#hash;
|
|
168
|
+
for (let i = 0; i < stage.k; i++) if (!stage.bits.get(probeAt(w0, w1, i, stage.m))) return false;
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
#anyHolds() {
|
|
172
|
+
for (let i = this.#stages.length - 1; i >= 0; i--) {
|
|
173
|
+
const stage = this.#stages[i];
|
|
174
|
+
if (stage && this.#holds(stage)) return true;
|
|
175
|
+
}
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
add(key) {
|
|
179
|
+
hash128KeyInto(key, this.#seed, this.#hash);
|
|
180
|
+
if (this.#anyHolds()) return;
|
|
181
|
+
if (this.#newest.count >= this.#newest.capacity) {
|
|
182
|
+
const i = this.#stages.length;
|
|
183
|
+
const next = this.#geometry(i);
|
|
184
|
+
if (next.m > MAX_BITS) throw new RangeError(`stage ${String(i)} needs ${String(next.m)} bits, more than ${String(MAX_BITS)}; the filter cannot grow further`);
|
|
185
|
+
this.#newest = this.#open(next);
|
|
186
|
+
}
|
|
187
|
+
const stage = this.#newest;
|
|
188
|
+
this.#probe(stage);
|
|
189
|
+
for (let i = 0; i < stage.k; i++) stage.bits.set(this.#probes[i] ?? 0);
|
|
190
|
+
stage.count++;
|
|
191
|
+
}
|
|
192
|
+
has(key) {
|
|
193
|
+
hash128KeyInto(key, this.#seed, this.#hash);
|
|
194
|
+
return this.#anyHolds();
|
|
195
|
+
}
|
|
196
|
+
rate() {
|
|
197
|
+
let miss = 1;
|
|
198
|
+
for (const s of this.#stages) miss *= 1 - (s.bits.count() / s.m) ** s.k;
|
|
199
|
+
return 1 - miss;
|
|
200
|
+
}
|
|
201
|
+
union(other) {
|
|
202
|
+
this.#assertMergeable(other);
|
|
203
|
+
const result = new ScalableBloomFilter({
|
|
204
|
+
n: this.#n,
|
|
205
|
+
epsilon: this.#epsilon,
|
|
206
|
+
growth: this.#growth,
|
|
207
|
+
tightening: this.#tightening,
|
|
208
|
+
seed: this.#seed
|
|
209
|
+
});
|
|
210
|
+
const [longer, shorter] = this.#stages.length >= other.#stages.length ? [this.#stages, other.#stages] : [other.#stages, this.#stages];
|
|
211
|
+
const stages = longer.map((stage, i) => {
|
|
212
|
+
const bits = new BitSet(stage.m);
|
|
213
|
+
bits.bytes.set(stage.bits.bytes);
|
|
214
|
+
const twin = shorter[i];
|
|
215
|
+
if (twin) {
|
|
216
|
+
const out = bits.bytes;
|
|
217
|
+
const bytes = twin.bits.bytes;
|
|
218
|
+
for (let j = 0; j < out.length; j++) out[j] = (out[j] ?? 0) | (bytes[j] ?? 0);
|
|
219
|
+
}
|
|
220
|
+
return {
|
|
221
|
+
bits,
|
|
222
|
+
m: stage.m,
|
|
223
|
+
k: stage.k,
|
|
224
|
+
capacity: stage.capacity,
|
|
225
|
+
count: Math.min(stage.capacity, stage.count + (twin?.count ?? 0))
|
|
226
|
+
};
|
|
227
|
+
});
|
|
228
|
+
result.#newest = result.#adopt(stages);
|
|
229
|
+
return result;
|
|
230
|
+
}
|
|
231
|
+
equals(other) {
|
|
232
|
+
if (this.#settingPairs(other).some(([, a, b]) => a !== b)) return false;
|
|
233
|
+
if (this.#stages.length !== other.#stages.length) return false;
|
|
234
|
+
return this.#stages.every((s, i) => {
|
|
235
|
+
const t = other.#stages[i];
|
|
236
|
+
if (!t) return false;
|
|
237
|
+
return s.m === t.m && s.k === t.k && s.capacity === t.capacity && s.count === t.count && bytesEqual(s.bits.bytes, t.bits.bytes);
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
static fromBytes(bytes) {
|
|
241
|
+
const { type, flags, body } = readHeader(bytes);
|
|
242
|
+
if (type !== TYPE) throw new SerializationError(`expected DSTL type ${String(TYPE)}, got ${String(type)}`);
|
|
243
|
+
if ((flags & 15) !== 0) throw new UnknownHashVariantError(`unsupported hash variant ${String(flags & 15)}`);
|
|
244
|
+
assertMinBodyLength(body.length, PARAMS_SIZE, "scalable");
|
|
245
|
+
assertParamsPadding(body, 36, PARAMS_SIZE, "scalable");
|
|
246
|
+
const view = new DataView(body.buffer, body.byteOffset, body.byteLength);
|
|
247
|
+
const stageCount = view.getUint32(32, true);
|
|
248
|
+
if (stageCount === 0) throw new SerializationError("scalable: frame declares no stages");
|
|
249
|
+
const tableEnd = PARAMS_SIZE + ENTRY_SIZE * stageCount;
|
|
250
|
+
assertMinBodyLength(body.length, tableEnd, "scalable");
|
|
251
|
+
const entries = readTable(view, stageCount);
|
|
252
|
+
const expected = entries.reduce((sum, e) => sum + padded8(Math.ceil(e.m / 8)), tableEnd);
|
|
253
|
+
assertBodyLength(body.length, expected, "scalable");
|
|
254
|
+
restoring = readStages(body, entries, tableEnd);
|
|
255
|
+
try {
|
|
256
|
+
return new ScalableBloomFilter({
|
|
257
|
+
n: view.getUint32(0, true),
|
|
258
|
+
seed: view.getUint32(4, true),
|
|
259
|
+
epsilon: view.getFloat64(8, true),
|
|
260
|
+
growth: view.getFloat64(16, true),
|
|
261
|
+
tightening: view.getFloat64(24, true)
|
|
262
|
+
});
|
|
263
|
+
} catch (err) {
|
|
264
|
+
if (err instanceof ParamError) throw new SerializationError(`scalable: ${err.message}`);
|
|
265
|
+
throw err;
|
|
266
|
+
} finally {
|
|
267
|
+
restoring = void 0;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
toBytes() {
|
|
271
|
+
const payload = this.#stages.reduce((sum, s) => sum + ENTRY_SIZE + padded8(s.bits.bytes.length), 0);
|
|
272
|
+
return writeFrame({
|
|
273
|
+
version: 5,
|
|
274
|
+
type: TYPE,
|
|
275
|
+
flags: 0
|
|
276
|
+
}, PARAMS_SIZE, payload, (body, view) => {
|
|
277
|
+
view.setUint32(0, this.#n, true);
|
|
278
|
+
view.setUint32(4, this.#seed, true);
|
|
279
|
+
view.setFloat64(8, this.#epsilon, true);
|
|
280
|
+
view.setFloat64(16, this.#growth, true);
|
|
281
|
+
view.setFloat64(24, this.#tightening, true);
|
|
282
|
+
view.setUint32(32, this.#stages.length, true);
|
|
283
|
+
let at = PARAMS_SIZE + ENTRY_SIZE * this.#stages.length;
|
|
284
|
+
this.#stages.forEach((s, i) => {
|
|
285
|
+
const entry = PARAMS_SIZE + ENTRY_SIZE * i;
|
|
286
|
+
view.setUint32(entry, s.m, true);
|
|
287
|
+
view.setUint16(entry + 4, s.k, true);
|
|
288
|
+
view.setUint32(entry + 8, s.capacity, true);
|
|
289
|
+
view.setUint32(entry + 12, s.count, true);
|
|
290
|
+
body.set(s.bits.bytes, at);
|
|
291
|
+
at += padded8(s.bits.bytes.length);
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
toJSON() {
|
|
296
|
+
return toJSONEnvelope(this.toBytes());
|
|
297
|
+
}
|
|
298
|
+
static fromJSON(value) {
|
|
299
|
+
return ScalableBloomFilter.fromBytes(fromJSONEnvelope(value));
|
|
300
|
+
}
|
|
301
|
+
get count() {
|
|
302
|
+
return this.#stages.reduce((sum, s) => sum + s.count, 0);
|
|
303
|
+
}
|
|
304
|
+
get capacity() {
|
|
305
|
+
return this.#stages.reduce((sum, s) => sum + s.capacity, 0);
|
|
306
|
+
}
|
|
307
|
+
get stages() {
|
|
308
|
+
return this.#stages.length;
|
|
309
|
+
}
|
|
310
|
+
get m() {
|
|
311
|
+
return this.#stages.reduce((sum, s) => sum + s.m, 0);
|
|
312
|
+
}
|
|
313
|
+
get bitsPerKey() {
|
|
314
|
+
return this.m / this.capacity;
|
|
315
|
+
}
|
|
316
|
+
get seed() {
|
|
317
|
+
return this.#seed;
|
|
318
|
+
}
|
|
319
|
+
get epsilon() {
|
|
320
|
+
return this.#epsilon;
|
|
321
|
+
}
|
|
322
|
+
get growth() {
|
|
323
|
+
return this.#growth;
|
|
324
|
+
}
|
|
325
|
+
get tightening() {
|
|
326
|
+
return this.#tightening;
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
//#endregion
|
|
330
|
+
export { BadMagicError, ChecksumError, ParamError, ReservedBitsError, ScalableBloomFilter, ScalableParamMismatchError, SerializationError, TruncatedError, UnknownHashVariantError, UnknownVersionError };
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
//#region src/core/bytes.d.ts
|
|
2
|
-
type BytesLike = string | Uint8Array | ArrayBuffer;
|
|
3
|
-
//#endregion
|
|
4
1
|
//#region src/core/serialize.d.ts
|
|
5
2
|
/**
|
|
6
3
|
* Base class for every defect `fromBytes` and `fromJSON` reject. Thrown
|
|
@@ -38,22 +35,36 @@ declare class BadMagicError extends SerializationError {
|
|
|
38
35
|
}
|
|
39
36
|
/**
|
|
40
37
|
* Thrown when a frame or JSON envelope declares a format version this release
|
|
41
|
-
* does not read.
|
|
42
|
-
* `distillate`
|
|
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
43
|
*/
|
|
44
44
|
declare class UnknownVersionError extends SerializationError {
|
|
45
45
|
/** Discriminates this error from other `Error`s. */
|
|
46
46
|
override readonly name = "UnknownVersionError";
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
|
-
* Thrown when a frame's flags nibble names a hash
|
|
50
|
-
* reproduce, so its stored bits are unreadable. Rebuild the filter from the
|
|
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
51
|
* source keys with the version you run.
|
|
52
52
|
*/
|
|
53
53
|
declare class UnknownHashVariantError extends SerializationError {
|
|
54
54
|
/** Discriminates this error from other `Error`s. */
|
|
55
55
|
override readonly name = "UnknownHashVariantError";
|
|
56
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
|
+
}
|
|
57
68
|
/**
|
|
58
69
|
* Thrown when a frame's CRC32 trailer does not match its contents, so the
|
|
59
70
|
* bytes were corrupted after they were written. Discard them and re-fetch;
|
|
@@ -72,5 +83,30 @@ interface FilterJSON {
|
|
|
72
83
|
/** Base64 of the `toBytes` frame. */
|
|
73
84
|
data: string;
|
|
74
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;
|
|
75
111
|
//#endregion
|
|
76
|
-
export {
|
|
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 };
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
//#region src/core/bytes.d.ts
|
|
2
|
-
type BytesLike = string | Uint8Array | ArrayBuffer;
|
|
3
|
-
//#endregion
|
|
4
1
|
//#region src/core/serialize.d.ts
|
|
5
2
|
/**
|
|
6
3
|
* Base class for every defect `fromBytes` and `fromJSON` reject. Thrown
|
|
@@ -38,22 +35,36 @@ declare class BadMagicError extends SerializationError {
|
|
|
38
35
|
}
|
|
39
36
|
/**
|
|
40
37
|
* Thrown when a frame or JSON envelope declares a format version this release
|
|
41
|
-
* does not read.
|
|
42
|
-
* `distillate`
|
|
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
43
|
*/
|
|
44
44
|
declare class UnknownVersionError extends SerializationError {
|
|
45
45
|
/** Discriminates this error from other `Error`s. */
|
|
46
46
|
override readonly name = "UnknownVersionError";
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
|
-
* Thrown when a frame's flags nibble names a hash
|
|
50
|
-
* reproduce, so its stored bits are unreadable. Rebuild the filter from the
|
|
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
51
|
* source keys with the version you run.
|
|
52
52
|
*/
|
|
53
53
|
declare class UnknownHashVariantError extends SerializationError {
|
|
54
54
|
/** Discriminates this error from other `Error`s. */
|
|
55
55
|
override readonly name = "UnknownHashVariantError";
|
|
56
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
|
+
}
|
|
57
68
|
/**
|
|
58
69
|
* Thrown when a frame's CRC32 trailer does not match its contents, so the
|
|
59
70
|
* bytes were corrupted after they were written. Discard them and re-fetch;
|
|
@@ -72,5 +83,30 @@ interface FilterJSON {
|
|
|
72
83
|
/** Base64 of the `toBytes` frame. */
|
|
73
84
|
data: string;
|
|
74
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;
|
|
75
111
|
//#endregion
|
|
76
|
-
export {
|
|
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 };
|