@elaraai/east 1.0.57 → 1.0.59
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/dist/src/serialization/beast2/index.d.ts +12 -1
- package/dist/src/serialization/beast2/index.d.ts.map +1 -1
- package/dist/src/serialization/beast2/index.js +20 -1
- package/dist/src/serialization/beast2/index.js.map +1 -1
- package/dist/src/serialization/beast2/v5/codec.d.ts +4 -1
- package/dist/src/serialization/beast2/v5/codec.d.ts.map +1 -1
- package/dist/src/serialization/beast2/v5/codec.js +5 -2
- package/dist/src/serialization/beast2/v5/codec.js.map +1 -1
- package/dist/src/serialization/beast2/v5/geometry.d.ts +241 -0
- package/dist/src/serialization/beast2/v5/geometry.d.ts.map +1 -0
- package/dist/src/serialization/beast2/v5/geometry.js +443 -0
- package/dist/src/serialization/beast2/v5/geometry.js.map +1 -0
- package/dist/src/serialization/beast2/v5/geometry.spec.d.ts +6 -0
- package/dist/src/serialization/beast2/v5/geometry.spec.d.ts.map +1 -0
- package/dist/src/serialization/beast2/v5/geometry.spec.js +283 -0
- package/dist/src/serialization/beast2/v5/geometry.spec.js.map +1 -0
- package/dist/src/serialization/beast2/v5/index.spec.js +18 -1
- package/dist/src/serialization/beast2/v5/index.spec.js.map +1 -1
- package/dist/src/serialization/beast2/v5/lazy.d.ts +79 -0
- package/dist/src/serialization/beast2/v5/lazy.d.ts.map +1 -0
- package/dist/src/serialization/beast2/v5/lazy.js +520 -0
- package/dist/src/serialization/beast2/v5/lazy.js.map +1 -0
- package/dist/src/serialization/beast2/v5/lazy.spec.d.ts +6 -0
- package/dist/src/serialization/beast2/v5/lazy.spec.d.ts.map +1 -0
- package/dist/src/serialization/beast2/v5/lazy.spec.js +239 -0
- package/dist/src/serialization/beast2/v5/lazy.spec.js.map +1 -0
- package/dist/src/serialization/beast2/v5/stream.d.ts +43 -3
- package/dist/src/serialization/beast2/v5/stream.d.ts.map +1 -1
- package/dist/src/serialization/beast2/v5/stream.js +103 -10
- package/dist/src/serialization/beast2/v5/stream.js.map +1 -1
- package/dist/src/serialization/index.d.ts +1 -1
- package/dist/src/serialization/index.d.ts.map +1 -1
- package/dist/src/serialization/index.js +1 -1
- package/dist/src/serialization/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Lazy pager-backed collection values — observational equivalence with the
|
|
7
|
+
* eager decode: lazy reads (size / get / has / iteration / index reads) and
|
|
8
|
+
* transparent hydration on everything else, for Dict, Set and Array roots.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, test } from "node:test";
|
|
11
|
+
import assert from "node:assert/strict";
|
|
12
|
+
import { IntegerType, StringType, ArrayType, SetType, DictType, StructType, FloatType, OptionType, RecursiveType, VariantType, RefType, VectorType, FunctionType, } from "../../../types.js";
|
|
13
|
+
import { compareFor, equalFor } from "../../../comparison.js";
|
|
14
|
+
import { SortedMap, SortedSet, isEastDict, isEastSet } from "../../../index.js";
|
|
15
|
+
import { decodeBeast2For, encodeBeast2For, encodeBeast2PagedFor, encodeBeast2SegmentsFor, openBeast2LazyFor, openBeast2PagesFor, isBeast2LazySafe, spliceBeast2, } from "../index.js";
|
|
16
|
+
const RowType = StructType({ id: IntegerType, name: StringType });
|
|
17
|
+
const TableType = DictType(IntegerType, RowType);
|
|
18
|
+
const PAGED = { batchSize: 100 };
|
|
19
|
+
function makeTable(n, offset = 0) {
|
|
20
|
+
const entries = [];
|
|
21
|
+
for (let i = 0; i < n; i++) {
|
|
22
|
+
const id = BigInt(i + offset);
|
|
23
|
+
entries.push([id, { id, name: `row-${i + offset}` }]);
|
|
24
|
+
}
|
|
25
|
+
return new SortedMap(entries, compareFor(IntegerType));
|
|
26
|
+
}
|
|
27
|
+
describe("Beast2 v5 — lazy Dict", () => {
|
|
28
|
+
test("lazy reads match the eager decode without hydration", () => {
|
|
29
|
+
const value = makeTable(350);
|
|
30
|
+
const blob = encodeBeast2PagedFor(TableType, PAGED)(value);
|
|
31
|
+
const lazy = openBeast2LazyFor(TableType)(blob);
|
|
32
|
+
assert.ok(lazy instanceof SortedMap);
|
|
33
|
+
assert.ok(isEastDict(lazy));
|
|
34
|
+
assert.equal(lazy.size, 350);
|
|
35
|
+
assert.equal(lazy.get(42n)?.name, "row-42");
|
|
36
|
+
assert.equal(lazy.get(9999n), undefined);
|
|
37
|
+
assert.ok(lazy.has(0n));
|
|
38
|
+
assert.ok(!lazy.has(-1n));
|
|
39
|
+
assert.equal(lazy.minKey(), 0n);
|
|
40
|
+
assert.equal(lazy.maxKey(), 349n);
|
|
41
|
+
assert.deepEqual([...lazy.keys()].slice(0, 3), [0n, 1n, 2n]);
|
|
42
|
+
const eq = equalFor(TableType);
|
|
43
|
+
assert.ok(eq(new SortedMap([...lazy], compareFor(IntegerType)), value), "iteration yields the whole value in canonical order");
|
|
44
|
+
});
|
|
45
|
+
test("mutation hydrates transparently and preserves identity semantics", () => {
|
|
46
|
+
const value = makeTable(250);
|
|
47
|
+
const blob = encodeBeast2PagedFor(TableType, PAGED)(value);
|
|
48
|
+
const lazy = openBeast2LazyFor(TableType)(blob);
|
|
49
|
+
lazy.set(9999n, { id: 9999n, name: "added" });
|
|
50
|
+
assert.equal(lazy.size, 251);
|
|
51
|
+
assert.equal(lazy.get(123n)?.name, "row-123");
|
|
52
|
+
assert.equal(lazy.get(9999n)?.name, "added");
|
|
53
|
+
assert.ok(lazy.delete(0n));
|
|
54
|
+
assert.equal(lazy.size, 250);
|
|
55
|
+
});
|
|
56
|
+
test("re-encoding a lazy value round-trips", () => {
|
|
57
|
+
const value = makeTable(150);
|
|
58
|
+
const blob = encodeBeast2PagedFor(TableType, PAGED)(value);
|
|
59
|
+
const lazy = openBeast2LazyFor(TableType)(blob);
|
|
60
|
+
const reencoded = encodeBeast2For(TableType)(lazy);
|
|
61
|
+
const eq = equalFor(TableType);
|
|
62
|
+
assert.ok(eq(decodeBeast2For(TableType)(reencoded), value));
|
|
63
|
+
});
|
|
64
|
+
test("empty blobs open as empty values", () => {
|
|
65
|
+
const blob = encodeBeast2PagedFor(TableType, PAGED)(makeTable(0));
|
|
66
|
+
const lazy = openBeast2LazyFor(TableType)(blob);
|
|
67
|
+
assert.ok(lazy instanceof SortedMap);
|
|
68
|
+
assert.equal(lazy.size, 0);
|
|
69
|
+
assert.equal(lazy.minKey(), undefined);
|
|
70
|
+
assert.equal(lazy.maxKey(), undefined);
|
|
71
|
+
assert.deepEqual([...lazy], []);
|
|
72
|
+
});
|
|
73
|
+
test("cross-segment order violations surface the canonical error", () => {
|
|
74
|
+
const high = encodeBeast2PagedFor(TableType, PAGED)(makeTable(100, 1000));
|
|
75
|
+
const low = encodeBeast2PagedFor(TableType, PAGED)(makeTable(100, 0));
|
|
76
|
+
const corrupt = spliceBeast2([high, low]);
|
|
77
|
+
const lazy = openBeast2LazyFor(TableType)(corrupt);
|
|
78
|
+
assert.throws(() => [...lazy], /not disjoint ascending key ranges/);
|
|
79
|
+
});
|
|
80
|
+
test("hydration mid-generator keeps the in-flight iterator on the original sequence", () => {
|
|
81
|
+
const value = makeTable(250);
|
|
82
|
+
const blob = encodeBeast2PagedFor(TableType, PAGED)(value);
|
|
83
|
+
const lazy = openBeast2LazyFor(TableType)(blob);
|
|
84
|
+
const it = lazy.entries();
|
|
85
|
+
const head = [it.next().value, it.next().value, it.next().value];
|
|
86
|
+
lazy.set(9999n, { id: 9999n, name: "added" }); // hydrates mid-generator
|
|
87
|
+
const rest = [...it];
|
|
88
|
+
const keys = [...head, ...rest].map(([k]) => k);
|
|
89
|
+
assert.equal(keys.length, 250, "the in-flight iterator completes the pre-hydration sequence");
|
|
90
|
+
for (let i = 1; i < keys.length; i++) {
|
|
91
|
+
assert.ok(keys[i - 1] < keys[i], "canonical ascending order throughout");
|
|
92
|
+
}
|
|
93
|
+
assert.equal([...lazy].length, 251, "a new iteration sees the mutation");
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
describe("Beast2 v5 — lazy Set", () => {
|
|
97
|
+
const Tags = SetType(StringType);
|
|
98
|
+
function makeTags(n) {
|
|
99
|
+
return new SortedSet(Array.from({ length: n }, (_, i) => `tag-${String(i).padStart(4, "0")}`), compareFor(StringType));
|
|
100
|
+
}
|
|
101
|
+
test("lazy reads match the eager decode without hydration", () => {
|
|
102
|
+
const value = makeTags(300);
|
|
103
|
+
const blob = encodeBeast2PagedFor(Tags, PAGED)(value);
|
|
104
|
+
const lazy = openBeast2LazyFor(Tags)(blob);
|
|
105
|
+
assert.ok(lazy instanceof SortedSet);
|
|
106
|
+
assert.ok(isEastSet(lazy));
|
|
107
|
+
assert.equal(lazy.size, 300);
|
|
108
|
+
assert.ok(lazy.has("tag-0042"));
|
|
109
|
+
assert.ok(!lazy.has("missing"));
|
|
110
|
+
assert.equal(lazy.minKey(), "tag-0000");
|
|
111
|
+
assert.equal(lazy.maxKey(), "tag-0299");
|
|
112
|
+
assert.deepEqual([...lazy].slice(0, 2), ["tag-0000", "tag-0001"]);
|
|
113
|
+
});
|
|
114
|
+
test("set algebra hydrates transparently", () => {
|
|
115
|
+
const value = makeTags(120);
|
|
116
|
+
const blob = encodeBeast2PagedFor(Tags, PAGED)(value);
|
|
117
|
+
const lazy = openBeast2LazyFor(Tags)(blob);
|
|
118
|
+
const other = new SortedSet(["tag-0000", "extra"], compareFor(StringType));
|
|
119
|
+
const union = lazy.union(other);
|
|
120
|
+
assert.equal(union.size, 121);
|
|
121
|
+
assert.ok(lazy.isSupersetOf(new SortedSet(["tag-0001"], compareFor(StringType))));
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
describe("Beast2 v5 — lazy Array", () => {
|
|
125
|
+
const Rows = ArrayType(StringType);
|
|
126
|
+
const rows = Array.from({ length: 260 }, (_, i) => `row-${i}`);
|
|
127
|
+
test("length, index reads, and iteration are lazy", () => {
|
|
128
|
+
const blob = encodeBeast2PagedFor(Rows, PAGED)(rows);
|
|
129
|
+
const lazy = openBeast2LazyFor(Rows)(blob);
|
|
130
|
+
assert.ok(Array.isArray(lazy));
|
|
131
|
+
assert.equal(lazy.length, 260);
|
|
132
|
+
assert.equal(lazy[0], "row-0");
|
|
133
|
+
assert.equal(lazy[259], "row-259");
|
|
134
|
+
assert.equal(lazy[260], undefined);
|
|
135
|
+
assert.deepEqual([...lazy], rows);
|
|
136
|
+
const collected = [];
|
|
137
|
+
for (const [i, v] of lazy.entries())
|
|
138
|
+
collected.push([i, v]);
|
|
139
|
+
assert.deepEqual(collected[0], [0, "row-0"]);
|
|
140
|
+
assert.equal(collected.length, 260);
|
|
141
|
+
});
|
|
142
|
+
test("any other operation hydrates transparently", () => {
|
|
143
|
+
const blob = encodeBeast2PagedFor(Rows, PAGED)(rows);
|
|
144
|
+
const lazy = openBeast2LazyFor(Rows)(blob);
|
|
145
|
+
assert.deepEqual(lazy.slice(10, 12), ["row-10", "row-11"]);
|
|
146
|
+
lazy.push("appended");
|
|
147
|
+
assert.equal(lazy.length, 261);
|
|
148
|
+
assert.equal(lazy[260], "appended");
|
|
149
|
+
assert.equal(lazy[0], "row-0");
|
|
150
|
+
});
|
|
151
|
+
test("hydration mid-iteration keeps the in-flight iterator on the original sequence", () => {
|
|
152
|
+
const blob = encodeBeast2PagedFor(Rows, PAGED)(rows);
|
|
153
|
+
const lazy = openBeast2LazyFor(Rows)(blob);
|
|
154
|
+
const it = lazy[Symbol.iterator]();
|
|
155
|
+
const head = [it.next().value, it.next().value];
|
|
156
|
+
lazy.push("appended"); // hydrates mid-generator
|
|
157
|
+
const rest = [...it];
|
|
158
|
+
assert.deepEqual([...head, ...rest], rows, "the in-flight iterator completes the pre-hydration sequence");
|
|
159
|
+
assert.equal(lazy.length, 261, "a fresh read sees the mutation");
|
|
160
|
+
});
|
|
161
|
+
test("non-canonical index strings behave exactly like the eager array", () => {
|
|
162
|
+
const blob = encodeBeast2PagedFor(Rows, PAGED)(rows);
|
|
163
|
+
const eager = decodeBeast2For(Rows)(blob);
|
|
164
|
+
const lazy = openBeast2LazyFor(Rows)(blob);
|
|
165
|
+
// `Number("01")` parses to 1, but "01" is an ordinary (absent) property
|
|
166
|
+
// on an eager array — the proxy must not serve an element for it.
|
|
167
|
+
for (const prop of ["", "01", " 2", "1e2", "-0", "2.0"]) {
|
|
168
|
+
assert.equal(lazy[prop], eager[prop], `property ${JSON.stringify(prop)}`);
|
|
169
|
+
}
|
|
170
|
+
assert.equal(lazy[2], "row-2", "canonical index reads still serve elements");
|
|
171
|
+
});
|
|
172
|
+
test("hydration handles very large segments without argument-limit overflow", () => {
|
|
173
|
+
const IntRows = ArrayType(IntegerType);
|
|
174
|
+
const big = Array.from({ length: 200_000 }, (_, i) => BigInt(i));
|
|
175
|
+
// One batch → one 200k-element segment: a spread-push hydration would
|
|
176
|
+
// overflow the engine's argument limit here.
|
|
177
|
+
const blob = encodeBeast2SegmentsFor(IntRows)([big]);
|
|
178
|
+
const lazy = openBeast2LazyFor(IntRows)(blob);
|
|
179
|
+
lazy.push(200000n); // hydrates
|
|
180
|
+
assert.equal(lazy.length, 200_001);
|
|
181
|
+
assert.equal(lazy[0], 0n);
|
|
182
|
+
assert.equal(lazy[199_999], 199999n);
|
|
183
|
+
assert.equal(lazy[200_000], 200000n);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
describe("Beast2 v5 — lazy shape gate (isBeast2LazySafe)", () => {
|
|
187
|
+
test("value-semantic element shapes are lazy-eligible", () => {
|
|
188
|
+
assert.ok(isBeast2LazySafe(ArrayType(IntegerType)));
|
|
189
|
+
assert.ok(isBeast2LazySafe(SetType(StringType)));
|
|
190
|
+
assert.ok(isBeast2LazySafe(DictType(IntegerType, StructType({ id: IntegerType, name: StringType }))));
|
|
191
|
+
assert.ok(isBeast2LazySafe(ArrayType(OptionType(StructType({ a: FloatType })))));
|
|
192
|
+
const Tree = RecursiveType((t) => VariantType({ leaf: IntegerType, pair: StructType({ l: t, r: t }) }));
|
|
193
|
+
assert.ok(isBeast2LazySafe(ArrayType(Tree)), "recursion without containers stays eligible");
|
|
194
|
+
});
|
|
195
|
+
test("mutable-nested and identity-compared element shapes open eager", () => {
|
|
196
|
+
assert.ok(!isBeast2LazySafe(ArrayType(ArrayType(IntegerType))), "nested array — writes through a read-out element would drop");
|
|
197
|
+
assert.ok(!isBeast2LazySafe(DictType(IntegerType, StructType({ xs: ArrayType(IntegerType) }))));
|
|
198
|
+
assert.ok(!isBeast2LazySafe(DictType(IntegerType, SetType(IntegerType))));
|
|
199
|
+
assert.ok(!isBeast2LazySafe(ArrayType(DictType(StringType, IntegerType))));
|
|
200
|
+
assert.ok(!isBeast2LazySafe(ArrayType(StructType({ r: RefType(IntegerType) }))));
|
|
201
|
+
assert.ok(!isBeast2LazySafe(ArrayType(VectorType(FloatType))), "`is()` compares vectors by identity");
|
|
202
|
+
assert.ok(!isBeast2LazySafe(SetType(VectorType(FloatType))));
|
|
203
|
+
assert.ok(!isBeast2LazySafe(ArrayType(FunctionType([], IntegerType))), "closures can capture mutable state");
|
|
204
|
+
const TreeWithList = RecursiveType((t) => VariantType({ leaf: ArrayType(IntegerType), pair: StructType({ l: t, r: t }) }));
|
|
205
|
+
assert.ok(!isBeast2LazySafe(ArrayType(TreeWithList)), "a container anywhere on the recursion is reachable");
|
|
206
|
+
});
|
|
207
|
+
test("non-collection roots are never lazy-eligible", () => {
|
|
208
|
+
assert.ok(!isBeast2LazySafe(StringType));
|
|
209
|
+
assert.ok(!isBeast2LazySafe(StructType({ a: IntegerType })));
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
describe("Beast2 v5 — pages segment cache", () => {
|
|
213
|
+
const RowsT = ArrayType(RowType);
|
|
214
|
+
const structRows = Array.from({ length: 500 }, (_, i) => ({ id: BigInt(i), name: `r-${i}` }));
|
|
215
|
+
test("element reads reuse the decoded segment; eviction decodes fresh", () => {
|
|
216
|
+
const pages = openBeast2PagesFor(RowsT)(encodeBeast2PagedFor(RowsT, PAGED)(structRows));
|
|
217
|
+
const a = pages.element(42);
|
|
218
|
+
const b = pages.element(43);
|
|
219
|
+
assert.equal(a, pages.element(42), "a re-read within the cache window returns the cached decode");
|
|
220
|
+
assert.equal(a.id, 42n);
|
|
221
|
+
assert.equal(b.id, 43n);
|
|
222
|
+
// Touch more segments than the cache holds; the first segment is evicted
|
|
223
|
+
// and re-decodes to a fresh (equal) object.
|
|
224
|
+
for (const row of [142, 242, 342, 442])
|
|
225
|
+
pages.element(row);
|
|
226
|
+
const again = pages.element(42);
|
|
227
|
+
assert.notEqual(again, a, "evicted segments decode fresh");
|
|
228
|
+
assert.deepEqual(again, a, "with identical content");
|
|
229
|
+
});
|
|
230
|
+
test("keyed reads reuse the decoded segment; the public segment() stays fresh", () => {
|
|
231
|
+
const pages = openBeast2PagesFor(TableType)(encodeBeast2PagedFor(TableType, PAGED)(makeTable(350)));
|
|
232
|
+
const v1 = pages.get(42n);
|
|
233
|
+
const v2 = pages.get(42n);
|
|
234
|
+
assert.equal(v1, v2, "the same cached segment serves repeated keyed reads");
|
|
235
|
+
assert.equal(v1.name, "row-42");
|
|
236
|
+
assert.notEqual(pages.segment(0), pages.segment(0), "segment() decodes fresh so callers cannot poison the cache");
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
//# sourceMappingURL=lazy.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lazy.spec.js","sourceRoot":"","sources":["../../../../../src/serialization/beast2/v5/lazy.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,6 +36,12 @@ export type Beast2WriterOptions = {
|
|
|
36
36
|
index?: boolean;
|
|
37
37
|
/** Source map for function values in the stream, written to the header. */
|
|
38
38
|
sourceMap?: SourceMap | null;
|
|
39
|
+
/** Emit these exact bytes as the blob's header (magic + type section +
|
|
40
|
+
* source-map section + root tag frame) instead of building one. The bytes
|
|
41
|
+
* must come from a v5 blob of the same wire type — used by splice tooling
|
|
42
|
+
* to rebuild segments byte-compatible with an existing blob's header.
|
|
43
|
+
* When set, `sourceMap` must be the prefix's own decoded source map. */
|
|
44
|
+
headerPrefix?: Uint8Array;
|
|
39
45
|
};
|
|
40
46
|
/**
|
|
41
47
|
* Append-only streaming writer for a v5 collection blob.
|
|
@@ -78,7 +84,8 @@ export declare class Beast2Writer<T extends EastType = EastType> {
|
|
|
78
84
|
* @param type - the collection type this stream holds (Array/Set/Dict)
|
|
79
85
|
* @param sink - receives output bytes as they are produced
|
|
80
86
|
* @param options - codec, self-containment, index, and source map options
|
|
81
|
-
* @throws {TypeError} When `type` is not an Array, Set or Dict type
|
|
87
|
+
* @throws {TypeError} When `type` is not an Array, Set or Dict type, or
|
|
88
|
+
* when `options.headerPrefix` is not a v5 header of exactly `type`.
|
|
82
89
|
*/
|
|
83
90
|
constructor(type: T | EastTypeValue, sink: (bytes: Uint8Array) => void, options?: Beast2WriterOptions);
|
|
84
91
|
/**
|
|
@@ -179,7 +186,10 @@ export declare function iterBeast2SegmentsFor<T extends EastType>(type: T | East
|
|
|
179
186
|
* Reads the footer + index once; `elementCount` is O(1) from the index, and
|
|
180
187
|
* {@link segment} seeks to and decodes exactly one segment. Requires the blob
|
|
181
188
|
* to carry an index (written by default by {@link Beast2Writer}); random
|
|
182
|
-
* access additionally requires self-contained segments.
|
|
189
|
+
* access additionally requires self-contained segments. The element and keyed
|
|
190
|
+
* read paths ({@link element} / {@link get}) reuse decoded segments through a
|
|
191
|
+
* small LRU, so a read loop over neighbouring rows decodes each segment once
|
|
192
|
+
* rather than once per element; {@link segment} itself always decodes fresh.
|
|
183
193
|
*
|
|
184
194
|
* Set/Dict blobs page like Arrays: the wire holds the canonical value split
|
|
185
195
|
* at segment boundaries (strictly ascending, disjoint segments), so row
|
|
@@ -211,6 +221,14 @@ export declare class Beast2Pages<T extends EastType = EastType> {
|
|
|
211
221
|
/** First key/element of each segment, in segment order (Set/Dict only). */
|
|
212
222
|
private fences;
|
|
213
223
|
private fenceDec;
|
|
224
|
+
/** Decoded segments kept hot for the element and keyed read paths, keyed
|
|
225
|
+
* by segment index in LRU order (mirrors east-c's `B2V5_PAGES_LRU`).
|
|
226
|
+
* Only {@link element} and {@link get} route through it — the public
|
|
227
|
+
* {@link segment} stays a fresh decode, so a caller mutating its result
|
|
228
|
+
* cannot poison the cache. `first`/`last` carry a Set/Dict segment's key
|
|
229
|
+
* range so a hit can maintain the caller's order threading without a
|
|
230
|
+
* container walk. */
|
|
231
|
+
private readonly segmentCache;
|
|
214
232
|
/** @internal Use {@link openBeast2PagesFor}. */
|
|
215
233
|
constructor(data: Uint8Array, typeValue: EastTypeValue, options?: Beast2DecodeOptions);
|
|
216
234
|
/** Number of segments in the blob. */
|
|
@@ -231,14 +249,36 @@ export declare class Beast2Pages<T extends EastType = EastType> {
|
|
|
231
249
|
segment(i: number): ValueTypeOf<T>;
|
|
232
250
|
/** Seeks to and decodes segment `i`, threading the caller's order state. */
|
|
233
251
|
private decodeSegmentCore;
|
|
252
|
+
/** Decodes segment `i` through the LRU cache, threading the caller's
|
|
253
|
+
* order state exactly as a fresh decode would: a hit replays the
|
|
254
|
+
* boundary-ascent check against the cached segment's first key and
|
|
255
|
+
* advances `order` to its last. Serves {@link element} and {@link get}
|
|
256
|
+
* only — see {@link segmentCache}. */
|
|
257
|
+
private segmentCached;
|
|
234
258
|
/** Decodes just the first key/element of segment `i` — a bounded probe
|
|
235
259
|
* (one frame inflate, one element decode), not a whole-segment decode. */
|
|
236
260
|
private firstKey;
|
|
261
|
+
/**
|
|
262
|
+
* Probes segment `i`'s fence: its first Dict key, Set element, or Array
|
|
263
|
+
* element, decoded without decoding the rest of the segment (one frame
|
|
264
|
+
* inflate, one element decode).
|
|
265
|
+
*
|
|
266
|
+
* For Set/Dict roots the fences bound each segment's canonical key range —
|
|
267
|
+
* segment `i` holds exactly the keys in `[fence(i), fence(i+1))` — which is
|
|
268
|
+
* what partition-boundary selection walks.
|
|
269
|
+
*
|
|
270
|
+
* @param i - zero-based segment index
|
|
271
|
+
* @returns the segment's first key or element
|
|
272
|
+
* @throws {Error} When `i` is out of range or the blob is not
|
|
273
|
+
* self-contained.
|
|
274
|
+
*/
|
|
275
|
+
fence(i: number): ValueTypeOf<T> extends Map<infer K, any> ? K : ValueTypeOf<T> extends Set<infer E> ? E : ValueTypeOf<T> extends (infer E)[] ? E : never;
|
|
237
276
|
/** Probes and verifies the segment fences once: each segment's first
|
|
238
277
|
* key/element must ascend strictly across segments. */
|
|
239
278
|
private verifyFences;
|
|
240
279
|
/** Decodes segment `i` with order threading, then checks its tail stays
|
|
241
|
-
* below the next segment's fence (segments must be disjoint ranges).
|
|
280
|
+
* below the next segment's fence (segments must be disjoint ranges).
|
|
281
|
+
* Pass `cached` on the keyed read path to route through the segment LRU. */
|
|
242
282
|
private decodeDisjoint;
|
|
243
283
|
/** Binary-searches the cumulative counts for the segment owning `row`,
|
|
244
284
|
* returning its index and the global row of its first element. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../../../../src/serialization/beast2/v5/stream.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../../../../src/serialization/beast2/v5/stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
* pageable and parallel-decodable; pass `selfContained: false` to keep
|
|
20
20
|
* whole-stream aliasing at the cost of random access.
|
|
21
21
|
*/
|
|
22
|
-
import {} from "../../../type_of_type.js";
|
|
22
|
+
import { EastTypeValueType, isTypeValueEqual } from "../../../type_of_type.js";
|
|
23
|
+
import { printFor } from "../../east.js";
|
|
23
24
|
import { BufferWriter, BufferReader } from "../../binary-utils.js";
|
|
24
25
|
import { SourceMap } from "../../../location.js";
|
|
25
26
|
import { compareFor } from "../../../comparison.js";
|
|
@@ -87,7 +88,8 @@ export class Beast2Writer {
|
|
|
87
88
|
* @param type - the collection type this stream holds (Array/Set/Dict)
|
|
88
89
|
* @param sink - receives output bytes as they are produced
|
|
89
90
|
* @param options - codec, self-containment, index, and source map options
|
|
90
|
-
* @throws {TypeError} When `type` is not an Array, Set or Dict type
|
|
91
|
+
* @throws {TypeError} When `type` is not an Array, Set or Dict type, or
|
|
92
|
+
* when `options.headerPrefix` is not a v5 header of exactly `type`.
|
|
91
93
|
*/
|
|
92
94
|
constructor(type, sink, options) {
|
|
93
95
|
const typeValue = asTypeValue(type);
|
|
@@ -118,7 +120,23 @@ export class Beast2Writer {
|
|
|
118
120
|
};
|
|
119
121
|
}
|
|
120
122
|
// Header: magic + type section + source map section, then the root tag
|
|
121
|
-
// as its own frame so every indexed segment frame is pure.
|
|
123
|
+
// as its own frame so every indexed segment frame is pure. A caller-
|
|
124
|
+
// provided prefix (splice tooling) is emitted verbatim instead — after
|
|
125
|
+
// verifying its wire type IS the declared type, since a mismatched
|
|
126
|
+
// prefix would write a blob whose header lies about its contents.
|
|
127
|
+
if (options?.headerPrefix !== undefined) {
|
|
128
|
+
verifyV5Magic(options.headerPrefix);
|
|
129
|
+
const prefixReader = new BufferReader(options.headerPrefix, MAGIC_BYTES_V5.length);
|
|
130
|
+
const { rootType } = readTypeSection(prefixReader);
|
|
131
|
+
if (!isTypeValueEqual(rootType, typeValue)) {
|
|
132
|
+
const printType = printFor(EastTypeValueType);
|
|
133
|
+
throw new TypeError(`beast2 v5: headerPrefix declares wire type ${printType(rootType)}, not the writer's ${printType(typeValue)} — the prefix must come from a blob of the same wire type`);
|
|
134
|
+
}
|
|
135
|
+
this.ctx.containerCount = 1;
|
|
136
|
+
this.ctx.segmentBaseDef = 1;
|
|
137
|
+
this.emit(options.headerPrefix);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
122
140
|
const head = new BufferWriter();
|
|
123
141
|
head.writeBytes(MAGIC_BYTES_V5);
|
|
124
142
|
writeTypeSection(typeValue, head);
|
|
@@ -507,13 +525,22 @@ export function iterBeast2SegmentsFor(type, options) {
|
|
|
507
525
|
// =============================================================================
|
|
508
526
|
// Paging reader
|
|
509
527
|
// =============================================================================
|
|
528
|
+
/** Decoded segments retained by a {@link Beast2Pages} for its element and
|
|
529
|
+
* keyed read paths (mirrors east-c's `B2V5_PAGES_LRU`): a keyed/indexed
|
|
530
|
+
* read loop over neighbouring rows then decodes each segment once instead
|
|
531
|
+
* of once per element. Bounded — at most this many decoded segments live
|
|
532
|
+
* per reader. */
|
|
533
|
+
const SEGMENT_CACHE_CAPACITY = 4;
|
|
510
534
|
/**
|
|
511
535
|
* Random access over an indexed, self-contained v5 collection blob.
|
|
512
536
|
*
|
|
513
537
|
* Reads the footer + index once; `elementCount` is O(1) from the index, and
|
|
514
538
|
* {@link segment} seeks to and decodes exactly one segment. Requires the blob
|
|
515
539
|
* to carry an index (written by default by {@link Beast2Writer}); random
|
|
516
|
-
* access additionally requires self-contained segments.
|
|
540
|
+
* access additionally requires self-contained segments. The element and keyed
|
|
541
|
+
* read paths ({@link element} / {@link get}) reuse decoded segments through a
|
|
542
|
+
* small LRU, so a read loop over neighbouring rows decodes each segment once
|
|
543
|
+
* rather than once per element; {@link segment} itself always decodes fresh.
|
|
517
544
|
*
|
|
518
545
|
* Set/Dict blobs page like Arrays: the wire holds the canonical value split
|
|
519
546
|
* at segment boundaries (strictly ascending, disjoint segments), so row
|
|
@@ -545,6 +572,14 @@ export class Beast2Pages {
|
|
|
545
572
|
/** First key/element of each segment, in segment order (Set/Dict only). */
|
|
546
573
|
fences = null;
|
|
547
574
|
fenceDec = null;
|
|
575
|
+
/** Decoded segments kept hot for the element and keyed read paths, keyed
|
|
576
|
+
* by segment index in LRU order (mirrors east-c's `B2V5_PAGES_LRU`).
|
|
577
|
+
* Only {@link element} and {@link get} route through it — the public
|
|
578
|
+
* {@link segment} stays a fresh decode, so a caller mutating its result
|
|
579
|
+
* cannot poison the cache. `first`/`last` carry a Set/Dict segment's key
|
|
580
|
+
* range so a hit can maintain the caller's order threading without a
|
|
581
|
+
* container walk. */
|
|
582
|
+
segmentCache = new Map();
|
|
548
583
|
/** @internal Use {@link openBeast2PagesFor}. */
|
|
549
584
|
constructor(data, typeValue, options) {
|
|
550
585
|
const { kind, sourceMap, frameOffset } = openSegmented(data, typeValue);
|
|
@@ -613,11 +648,45 @@ export class Beast2Pages {
|
|
|
613
648
|
}
|
|
614
649
|
return value;
|
|
615
650
|
}
|
|
651
|
+
/** Decodes segment `i` through the LRU cache, threading the caller's
|
|
652
|
+
* order state exactly as a fresh decode would: a hit replays the
|
|
653
|
+
* boundary-ascent check against the cached segment's first key and
|
|
654
|
+
* advances `order` to its last. Serves {@link element} and {@link get}
|
|
655
|
+
* only — see {@link segmentCache}. */
|
|
656
|
+
segmentCached(i, order) {
|
|
657
|
+
const hit = this.segmentCache.get(i);
|
|
658
|
+
if (hit !== undefined) {
|
|
659
|
+
this.segmentCache.delete(i);
|
|
660
|
+
this.segmentCache.set(i, hit); // refresh recency
|
|
661
|
+
if (order !== undefined && this.orderCmp !== null) {
|
|
662
|
+
if (order.has && this.orderCmp(order.prev, hit.first) >= 0) {
|
|
663
|
+
throw new Error(`beast2 v5: ${this.kind === "Dict" ? "Dict keys" : "Set elements"} are not strictly ascending in East order — the wire must hold the canonical value (corrupt or pre-contract blob)`);
|
|
664
|
+
}
|
|
665
|
+
order.prev = hit.last;
|
|
666
|
+
order.has = true;
|
|
667
|
+
}
|
|
668
|
+
return hit.seg;
|
|
669
|
+
}
|
|
670
|
+
const seg = this.decodeSegmentCore(i, order);
|
|
671
|
+
let first;
|
|
672
|
+
let last;
|
|
673
|
+
if (this.kind !== "Array") {
|
|
674
|
+
first = (this.kind === "Set" ? seg.values() : seg.keys()).next().value;
|
|
675
|
+
// Segments are never empty, so a Set/Dict decode leaves the caller's
|
|
676
|
+
// order state on the segment's last key.
|
|
677
|
+
last = order?.prev;
|
|
678
|
+
}
|
|
679
|
+
this.segmentCache.set(i, { seg, first, last });
|
|
680
|
+
if (this.segmentCache.size > SEGMENT_CACHE_CAPACITY) {
|
|
681
|
+
this.segmentCache.delete(this.segmentCache.keys().next().value);
|
|
682
|
+
}
|
|
683
|
+
return seg;
|
|
684
|
+
}
|
|
616
685
|
/** Decodes just the first key/element of segment `i` — a bounded probe
|
|
617
686
|
* (one frame inflate, one element decode), not a whole-segment decode. */
|
|
618
687
|
firstKey(i) {
|
|
619
688
|
if (!this.fenceDec) {
|
|
620
|
-
const keyType = this.kind === "
|
|
689
|
+
const keyType = this.kind === "Dict" ? this.typeValue.value.key : this.typeValue.value;
|
|
621
690
|
this.fenceDec = buildV5Decoder(keyType);
|
|
622
691
|
}
|
|
623
692
|
const cursor = new FrameReader(this.data, this.indexData.offsets[i]);
|
|
@@ -626,6 +695,29 @@ export class Beast2Pages {
|
|
|
626
695
|
const ctx = { containers: [], sourceMap: this.sourceMap, ...buildPlatformContext(this.platform) };
|
|
627
696
|
return this.fenceDec(reader, ctx);
|
|
628
697
|
}
|
|
698
|
+
/**
|
|
699
|
+
* Probes segment `i`'s fence: its first Dict key, Set element, or Array
|
|
700
|
+
* element, decoded without decoding the rest of the segment (one frame
|
|
701
|
+
* inflate, one element decode).
|
|
702
|
+
*
|
|
703
|
+
* For Set/Dict roots the fences bound each segment's canonical key range —
|
|
704
|
+
* segment `i` holds exactly the keys in `[fence(i), fence(i+1))` — which is
|
|
705
|
+
* what partition-boundary selection walks.
|
|
706
|
+
*
|
|
707
|
+
* @param i - zero-based segment index
|
|
708
|
+
* @returns the segment's first key or element
|
|
709
|
+
* @throws {Error} When `i` is out of range or the blob is not
|
|
710
|
+
* self-contained.
|
|
711
|
+
*/
|
|
712
|
+
fence(i) {
|
|
713
|
+
if (!this.selfContained) {
|
|
714
|
+
throw new Error(`beast2 v5: blob has cross-segment aliasing — random access needs self-contained segments`);
|
|
715
|
+
}
|
|
716
|
+
if (i < 0 || i >= this.indexData.offsets.length) {
|
|
717
|
+
throw new Error(`beast2 v5: segment ${i} out of range (${this.indexData.offsets.length} segments)`);
|
|
718
|
+
}
|
|
719
|
+
return this.firstKey(i);
|
|
720
|
+
}
|
|
629
721
|
/** Probes and verifies the segment fences once: each segment's first
|
|
630
722
|
* key/element must ascend strictly across segments. */
|
|
631
723
|
verifyFences() {
|
|
@@ -647,9 +739,10 @@ export class Beast2Pages {
|
|
|
647
739
|
return fences;
|
|
648
740
|
}
|
|
649
741
|
/** Decodes segment `i` with order threading, then checks its tail stays
|
|
650
|
-
* below the next segment's fence (segments must be disjoint ranges).
|
|
651
|
-
|
|
652
|
-
|
|
742
|
+
* below the next segment's fence (segments must be disjoint ranges).
|
|
743
|
+
* Pass `cached` on the keyed read path to route through the segment LRU. */
|
|
744
|
+
decodeDisjoint(i, order, fences, cached = false) {
|
|
745
|
+
const value = cached ? this.segmentCached(i, order) : this.decodeSegmentCore(i, order);
|
|
653
746
|
if (i + 1 < fences.length && order.has && this.orderCmp(order.prev, fences[i + 1]) >= 0) {
|
|
654
747
|
throw new Error(`beast2 v5: segments ${i} and ${i + 1} are not disjoint ascending ${this.kind === "Dict" ? "key" : "element"} ranges — the wire must hold the canonical value (corrupt or pre-contract blob)`);
|
|
655
748
|
}
|
|
@@ -684,7 +777,7 @@ export class Beast2Pages {
|
|
|
684
777
|
throw new Error(`beast2 v5: element ${row} out of range (${this.elementCount} elements)`);
|
|
685
778
|
}
|
|
686
779
|
const { seg, base } = this.rowSegment(row);
|
|
687
|
-
const segment = this.
|
|
780
|
+
const segment = this.segmentCached(seg, undefined);
|
|
688
781
|
return segment[row - base];
|
|
689
782
|
}
|
|
690
783
|
/**
|
|
@@ -799,7 +892,7 @@ export class Beast2Pages {
|
|
|
799
892
|
hi = mid - 1;
|
|
800
893
|
}
|
|
801
894
|
const order = { prev: undefined, has: false };
|
|
802
|
-
const segment = this.decodeDisjoint(lo, order, fences);
|
|
895
|
+
const segment = this.decodeDisjoint(lo, order, fences, true);
|
|
803
896
|
if (this.kind === "Set") {
|
|
804
897
|
for (const item of segment) {
|
|
805
898
|
if (this.orderCmp(item, key) === 0)
|