@elaraai/east 1.0.69 → 1.0.71

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.
Files changed (82) hide show
  1. package/dist/src/builtins.d.ts +1 -1
  2. package/dist/src/builtins.d.ts.map +1 -1
  3. package/dist/src/builtins.js +7 -0
  4. package/dist/src/builtins.js.map +1 -1
  5. package/dist/src/codegen/spellings.d.ts.map +1 -1
  6. package/dist/src/codegen/spellings.js +1 -0
  7. package/dist/src/codegen/spellings.js.map +1 -1
  8. package/dist/src/compile.d.ts.map +1 -1
  9. package/dist/src/compile.js +50 -2
  10. package/dist/src/compile.js.map +1 -1
  11. package/dist/src/compile.open_beast.spec.d.ts +6 -0
  12. package/dist/src/compile.open_beast.spec.d.ts.map +1 -0
  13. package/dist/src/compile.open_beast.spec.js +99 -0
  14. package/dist/src/compile.open_beast.spec.js.map +1 -0
  15. package/dist/src/expr/blob.d.ts +41 -1
  16. package/dist/src/expr/blob.d.ts.map +1 -1
  17. package/dist/src/expr/blob.js +52 -0
  18. package/dist/src/expr/blob.js.map +1 -1
  19. package/dist/src/expr/libs/datetime.d.ts +11 -0
  20. package/dist/src/expr/libs/datetime.d.ts.map +1 -1
  21. package/dist/src/expr/libs/datetime.js +11 -0
  22. package/dist/src/expr/libs/datetime.js.map +1 -1
  23. package/dist/src/location.d.ts +12 -0
  24. package/dist/src/location.d.ts.map +1 -1
  25. package/dist/src/location.js +15 -3
  26. package/dist/src/location.js.map +1 -1
  27. package/dist/src/serialization/beast2/index.d.ts +16 -1
  28. package/dist/src/serialization/beast2/index.d.ts.map +1 -1
  29. package/dist/src/serialization/beast2/index.js +24 -3
  30. package/dist/src/serialization/beast2/index.js.map +1 -1
  31. package/dist/src/serialization/beast2/v4/container.d.ts +10 -0
  32. package/dist/src/serialization/beast2/v4/container.d.ts.map +1 -1
  33. package/dist/src/serialization/beast2/v4/container.js +13 -0
  34. package/dist/src/serialization/beast2/v4/container.js.map +1 -1
  35. package/dist/src/serialization/beast2/v5/frames.d.ts +17 -0
  36. package/dist/src/serialization/beast2/v5/frames.d.ts.map +1 -1
  37. package/dist/src/serialization/beast2/v5/frames.js +40 -0
  38. package/dist/src/serialization/beast2/v5/frames.js.map +1 -1
  39. package/dist/src/serialization/beast2/v5/geometry.d.ts +10 -113
  40. package/dist/src/serialization/beast2/v5/geometry.d.ts.map +1 -1
  41. package/dist/src/serialization/beast2/v5/geometry.js +7 -151
  42. package/dist/src/serialization/beast2/v5/geometry.js.map +1 -1
  43. package/dist/src/serialization/beast2/v5/lazy.d.ts +8 -2
  44. package/dist/src/serialization/beast2/v5/lazy.d.ts.map +1 -1
  45. package/dist/src/serialization/beast2/v5/lazy.js +9 -3
  46. package/dist/src/serialization/beast2/v5/lazy.js.map +1 -1
  47. package/dist/src/serialization/beast2/v5/range.d.ts +201 -0
  48. package/dist/src/serialization/beast2/v5/range.d.ts.map +1 -0
  49. package/dist/src/serialization/beast2/v5/range.js +252 -0
  50. package/dist/src/serialization/beast2/v5/range.js.map +1 -0
  51. package/dist/src/serialization/beast2/v5/stream.d.ts +29 -5
  52. package/dist/src/serialization/beast2/v5/stream.d.ts.map +1 -1
  53. package/dist/src/serialization/beast2/v5/stream.js +86 -19
  54. package/dist/src/serialization/beast2/v5/stream.js.map +1 -1
  55. package/dist/src/serialization/beast2/v5/sync-reader.spec.d.ts +6 -0
  56. package/dist/src/serialization/beast2/v5/sync-reader.spec.d.ts.map +1 -0
  57. package/dist/src/serialization/beast2/v5/sync-reader.spec.js +228 -0
  58. package/dist/src/serialization/beast2/v5/sync-reader.spec.js.map +1 -0
  59. package/dist/src/serialization/index.d.ts +3 -1
  60. package/dist/src/serialization/index.d.ts.map +1 -1
  61. package/dist/src/serialization/index.js +3 -1
  62. package/dist/src/serialization/index.js.map +1 -1
  63. package/dist/src/serialization/json.d.ts.map +1 -1
  64. package/dist/src/serialization/json.js +31 -1
  65. package/dist/src/serialization/json.js.map +1 -1
  66. package/dist/src/serialization/json_schema.d.ts +76 -0
  67. package/dist/src/serialization/json_schema.d.ts.map +1 -0
  68. package/dist/src/serialization/json_schema.js +290 -0
  69. package/dist/src/serialization/json_schema.js.map +1 -0
  70. package/dist/src/serialization/json_schema.spec.d.ts +2 -0
  71. package/dist/src/serialization/json_schema.spec.d.ts.map +1 -0
  72. package/dist/src/serialization/json_schema.spec.js +327 -0
  73. package/dist/src/serialization/json_schema.spec.js.map +1 -0
  74. package/dist/src/serialization/json_schema_to_type.d.ts +74 -0
  75. package/dist/src/serialization/json_schema_to_type.d.ts.map +1 -0
  76. package/dist/src/serialization/json_schema_to_type.js +500 -0
  77. package/dist/src/serialization/json_schema_to_type.js.map +1 -0
  78. package/dist/src/serialization/json_schema_to_type.spec.d.ts +2 -0
  79. package/dist/src/serialization/json_schema_to_type.spec.d.ts.map +1 -0
  80. package/dist/src/serialization/json_schema_to_type.spec.js +372 -0
  81. package/dist/src/serialization/json_schema_to_type.spec.js.map +1 -0
  82. package/package.json +1 -1
@@ -0,0 +1,252 @@
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
+ * Beast2 v5 ranged access — reading a segmented, indexed blob's geometry
7
+ * through positioned byte reads instead of a whole buffer.
8
+ *
9
+ * A v5 collection blob is `header · tag frame · segment frames · terminator
10
+ * frame · index · footer`, so its whole geometry is recoverable from two
11
+ * ranged reads: the tail (footer + index) and the head (header sections +
12
+ * tag frame). Every segment frame's byte range is then known up front, and a
13
+ * paging reader fetches only the frames it decodes: an Array index read or
14
+ * a Set/Dict keyed read touches one frame, iteration touches each frame
15
+ * once. The exception is a Set/Dict root's FIRST keyed read, which verifies
16
+ * the segment fences by probing every frame once (as east-c does) — a
17
+ * bounded prefix of each frame, read and inflated as far as it goes, never
18
+ * the frame unless its first key is wider than the probe. I/O is O(header +
19
+ * index + touched frames) in every case; peak memory is O(segment).
20
+ *
21
+ * Two reader shapes serve two consumers: {@link Beast2RangeReader} (async —
22
+ * an HTTP range request, an S3 ranged GET, e3's dataset paging) and
23
+ * {@link Beast2SyncRangeReader} (sync — a file descriptor with positioned
24
+ * reads, a memory mapping, a plain `Uint8Array`), which is what a compiled
25
+ * East body drives through `Beast2Pages` and `openBeast2LazyFor`. Core stays
26
+ * free of any file system: the reader is injected.
27
+ */
28
+ import {} from "../../../type_of_type.js";
29
+ import { BufferReader } from "../../binary-utils.js";
30
+ import { readTypeSection } from "./type-section.js";
31
+ import { MAGIC_BYTES_V5, FOOTER_MAGIC_V5, INDEX_FLAG_SELF_CONTAINED, readSourceMapSectionV5, isSegmentedRoot, } from "./codec.js";
32
+ /** The exact bytes of the root NEW tag frame and of the terminator frame:
33
+ * codec `none`, one logical byte, payload `0x00`. */
34
+ export const TAG_OR_TERMINATOR_FRAME = new Uint8Array([0x00, 0x01, 0x01, 0x00]);
35
+ /** Whether `source` is a {@link Beast2SyncRangeReader} rather than a blob —
36
+ * judged by shape, since a typed array from another realm fails
37
+ * `instanceof Uint8Array`. */
38
+ export function isBeast2SyncRangeReader(source) {
39
+ const r = source;
40
+ return r !== null && typeof r === "object" && typeof r.read === "function" && typeof r.size === "number";
41
+ }
42
+ /**
43
+ * Reads exactly `length` bytes at `offset` through a sync reader, refusing a
44
+ * short result up front: a reader that returns fewer bytes (a bare
45
+ * `readSync` without the retry loop) would otherwise be reported as a
46
+ * malformed blob.
47
+ *
48
+ * @param reader - the reader
49
+ * @param offset - absolute byte offset
50
+ * @param length - number of bytes
51
+ * @returns exactly the requested bytes
52
+ * @throws {Error} When the reader returns a different number of bytes.
53
+ */
54
+ export function readExact(reader, offset, length) {
55
+ const bytes = reader.read(offset, length);
56
+ if (bytes.length !== length) {
57
+ throw new Error(`beast2 v5: reader returned ${bytes.length} bytes for a ${length}-byte range at offset ${offset}`);
58
+ }
59
+ return bytes;
60
+ }
61
+ /** Whether the 4 bytes at `offset` are a tag/terminator frame. */
62
+ export function isTagOrTerminatorFrame(data, offset) {
63
+ if (offset + 4 > data.length)
64
+ return false;
65
+ for (let i = 0; i < 4; i++) {
66
+ if (data[offset + i] !== TAG_OR_TERMINATOR_FRAME[i])
67
+ return false;
68
+ }
69
+ return true;
70
+ }
71
+ /** Parses the u64 little-endian index offset from 8 bytes at `at`. */
72
+ export function readU64LE(data, at) {
73
+ let value = 0n;
74
+ for (let i = 7; i >= 0; i--) {
75
+ value = (value << 8n) | BigInt(data[at + i]);
76
+ }
77
+ return Number(value);
78
+ }
79
+ /** The size of the initial tail read: the footer plus a probe of the index. */
80
+ function tailProbeSize(size, options) {
81
+ return Math.min(size, Math.max(options?.tailProbeBytes ?? 64 * 1024, 16));
82
+ }
83
+ /** Reads the footer from a tail read holding `[tailStart, size)`: the index
84
+ * offset, validated against the blob size. */
85
+ function footerIndexOffset(tail, tailStart, size) {
86
+ const footerStart = size - 16;
87
+ for (let i = 0; i < 8; i++) {
88
+ if (tail[footerStart + 8 + i - tailStart] !== FOOTER_MAGIC_V5[i]) {
89
+ throw new Error(`beast2 v5: blob carries no index — ranged reads need one (write with the index enabled, the default)`);
90
+ }
91
+ }
92
+ const indexOffset = readU64LE(tail, footerStart - tailStart);
93
+ if (indexOffset < MAGIC_BYTES_V5.length || indexOffset >= footerStart) {
94
+ throw new Error(`beast2 v5: footer index offset ${indexOffset} out of range`);
95
+ }
96
+ return indexOffset;
97
+ }
98
+ /** Parses the index section and checks the terminator frame from a tail
99
+ * read holding `[tailStart, size)` that reaches back to the terminator. */
100
+ function parseIndexTail(tail, tailStart, size, indexOffset) {
101
+ const footerStart = size - 16;
102
+ const segmentsEnd = indexOffset - TAG_OR_TERMINATOR_FRAME.length;
103
+ const indexReader = new BufferReader(tail, indexOffset - tailStart);
104
+ const flags = indexReader.readVarint();
105
+ if ((flags & ~INDEX_FLAG_SELF_CONTAINED) !== 0) {
106
+ throw new Error(`beast2 v5: unknown index flags 0x${flags.toString(16)}`);
107
+ }
108
+ const segmentCount = indexReader.readVarint();
109
+ const offsets = new Array(segmentCount);
110
+ const counts = new Array(segmentCount);
111
+ let prev = 0;
112
+ let elementCount = 0;
113
+ for (let i = 0; i < segmentCount; i++) {
114
+ prev += indexReader.readVarint();
115
+ offsets[i] = prev;
116
+ counts[i] = indexReader.readVarint();
117
+ elementCount += counts[i];
118
+ if (prev >= indexOffset) {
119
+ throw new Error(`beast2 v5: index segment offset ${prev} overlaps the index section`);
120
+ }
121
+ }
122
+ if (indexReader.offset !== footerStart - tailStart) {
123
+ throw new Error(`beast2 v5: index section size mismatch (ends at ${indexReader.offset + tailStart}, footer at ${footerStart})`);
124
+ }
125
+ if (!isTagOrTerminatorFrame(tail, segmentsEnd - tailStart)) {
126
+ throw new Error(`beast2 v5: terminator frame not found where expected (offset ${segmentsEnd})`);
127
+ }
128
+ return { segmentsEnd, offsets, counts, elementCount, selfContained: (flags & INDEX_FLAG_SELF_CONTAINED) !== 0 };
129
+ }
130
+ /** Parses the header sections + root tag frame from a head read holding
131
+ * `[0, prefixEnd)`: the v5 magic, a collection root type, the source-map
132
+ * section, and the tag frame ending exactly at `prefixEnd`. */
133
+ function parseHead(head, prefixEnd) {
134
+ for (let i = 0; i < 8; i++) {
135
+ if (head[i] !== MAGIC_BYTES_V5[i]) {
136
+ if (i === 7 && head[i] === 0x04) {
137
+ throw new Error(`beast2 v5: ranged reads need v5 blobs; this is a v4 container (re-encode with version 5)`);
138
+ }
139
+ throw new Error(`beast2 v5: not a beast2 v5 container`);
140
+ }
141
+ }
142
+ const headReader = new BufferReader(head, MAGIC_BYTES_V5.length);
143
+ const { rootType } = readTypeSection(headReader);
144
+ if (!isSegmentedRoot(rootType)) {
145
+ throw new Error(`beast2 v5: ranged reads address Array, Set or Dict roots, not ${rootType.type}`);
146
+ }
147
+ const sourceMap = readSourceMapSectionV5(headReader);
148
+ const frameOffset = headReader.offset;
149
+ if (frameOffset + 4 !== prefixEnd || !isTagOrTerminatorFrame(head, frameOffset)) {
150
+ throw new Error(`beast2 v5: root tag frame not found where expected (offset ${frameOffset})`);
151
+ }
152
+ return { rootType, sourceMapEmpty: sourceMap.size <= 1n };
153
+ }
154
+ /** Assembles the extents from the parsed tail and head. */
155
+ function assembleExtents(size, indexOffset, index, prefixEnd, head) {
156
+ const { rootType, sourceMapEmpty } = parseHead(head, prefixEnd);
157
+ return {
158
+ prefixEnd,
159
+ segmentsEnd: index.segmentsEnd,
160
+ indexOffset,
161
+ offsets: index.offsets,
162
+ counts: index.counts,
163
+ elementCount: index.elementCount,
164
+ selfContained: index.selfContained,
165
+ sourceMapEmpty,
166
+ typeValue: rootType,
167
+ size,
168
+ head,
169
+ };
170
+ }
171
+ /**
172
+ * Reads the byte geometry of a segmented, indexed v5 collection blob through
173
+ * ranged access — the footer and index from a tail read, the header sections
174
+ * from a head read — without ever buffering the blob whole.
175
+ *
176
+ * The result carries everything `carveBeast2Ranged` needs to assemble a
177
+ * standalone blob for any segment span whose frame bytes are then the only
178
+ * further reads: total I/O for a window is O(header + index + window), not
179
+ * O(blob).
180
+ *
181
+ * @param reader - ranged access to the blob
182
+ * @param options - tail-probe tuning
183
+ * @returns the blob's {@link Beast2RangedExtents}
184
+ * @throws {Error} When the blob is not a v5 container, its root is not a
185
+ * collection, it carries no index, or the frame geometry is malformed —
186
+ * the same conditions `readBeast2Extents` rejects.
187
+ */
188
+ export async function readBeast2ExtentsRanged(reader, options) {
189
+ const size = reader.size;
190
+ if (size < MAGIC_BYTES_V5.length + 16) {
191
+ throw new Error(`Data too short for Beast2 format: ${size} bytes`);
192
+ }
193
+ // Tail: footer first, then the index section (one further read when the
194
+ // probe missed its start).
195
+ let tailStart = size - tailProbeSize(size, options);
196
+ let tail = checkedLength(await reader.read(tailStart, size - tailStart), tailStart, size - tailStart);
197
+ const indexOffset = footerIndexOffset(tail, tailStart, size);
198
+ const segmentsEnd = indexOffset - TAG_OR_TERMINATOR_FRAME.length;
199
+ if (segmentsEnd < tailStart) {
200
+ tailStart = segmentsEnd;
201
+ tail = checkedLength(await reader.read(tailStart, size - tailStart), tailStart, size - tailStart);
202
+ }
203
+ const index = parseIndexTail(tail, tailStart, size, indexOffset);
204
+ // Head: header sections + root tag frame, ending exactly where the first
205
+ // segment starts (or at the terminator, for an empty blob).
206
+ const prefixEnd = index.offsets.length > 0 ? index.offsets[0] : segmentsEnd;
207
+ const head = checkedLength(await reader.read(0, prefixEnd), 0, prefixEnd);
208
+ return assembleExtents(size, indexOffset, index, prefixEnd, head);
209
+ }
210
+ /** The exact-length check {@link readExact} applies, for an awaited read. */
211
+ function checkedLength(bytes, offset, length) {
212
+ if (bytes.length !== length) {
213
+ throw new Error(`beast2 v5: reader returned ${bytes.length} bytes for a ${length}-byte range at offset ${offset}`);
214
+ }
215
+ return bytes;
216
+ }
217
+ /**
218
+ * The synchronous twin of {@link readBeast2ExtentsRanged}: the same two
219
+ * ranged reads (tail, then head) through a {@link Beast2SyncRangeReader},
220
+ * for the paging readers a compiled body drives without awaiting.
221
+ *
222
+ * @param reader - synchronous ranged access to the blob
223
+ * @param options - tail-probe tuning
224
+ * @returns the blob's {@link Beast2RangedExtents}
225
+ * @throws {Error} When the blob is not a v5 container, its root is not a
226
+ * collection, it carries no index, or the frame geometry is malformed.
227
+ */
228
+ export function readBeast2ExtentsSync(reader, options) {
229
+ const size = reader.size;
230
+ if (size < MAGIC_BYTES_V5.length + 16) {
231
+ throw new Error(`Data too short for Beast2 format: ${size} bytes`);
232
+ }
233
+ let tailStart = size - tailProbeSize(size, options);
234
+ let tail = readExact(reader, tailStart, size - tailStart);
235
+ const indexOffset = footerIndexOffset(tail, tailStart, size);
236
+ const segmentsEnd = indexOffset - TAG_OR_TERMINATOR_FRAME.length;
237
+ if (segmentsEnd < tailStart) {
238
+ tailStart = segmentsEnd;
239
+ tail = readExact(reader, tailStart, size - tailStart);
240
+ }
241
+ const index = parseIndexTail(tail, tailStart, size, indexOffset);
242
+ const prefixEnd = index.offsets.length > 0 ? index.offsets[0] : segmentsEnd;
243
+ const head = readExact(reader, 0, prefixEnd);
244
+ return assembleExtents(size, indexOffset, index, prefixEnd, head);
245
+ }
246
+ /** A {@link Beast2SyncRangeReader} over a whole in-memory blob: reads are
247
+ * zero-copy views. What the `Uint8Array` entry points wrap, so every paging
248
+ * reader has one source shape. */
249
+ export function bytesReader(data) {
250
+ return { size: data.length, read: (offset, length) => data.subarray(offset, offset + length) };
251
+ }
252
+ //# sourceMappingURL=range.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"range.js","sourceRoot":"","sources":["../../../../../src/serialization/beast2/v5/range.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,7 @@ import type { EastType, ValueTypeOf } from "../../../types.js";
24
24
  import { SourceMap } from "../../../location.js";
25
25
  import { type Beast2DecodeOptions } from "../shared.js";
26
26
  import { type Beast2Codec } from "./frames.js";
27
+ import { type Beast2SyncRangeReader } from "./range.js";
27
28
  /** Options accepted by {@link Beast2Writer} and {@link encodeBeast2SegmentsFor}. */
28
29
  export type Beast2WriterOptions = {
29
30
  /** Per-frame codec. Defaults to `"deflate"`. */
@@ -191,6 +192,15 @@ export declare function iterBeast2SegmentsFor<T extends EastType>(type: T | East
191
192
  * small LRU, so a read loop over neighbouring rows decodes each segment once
192
193
  * rather than once per element; {@link segment} itself always decodes fresh.
193
194
  *
195
+ * The blob is either a whole `Uint8Array` or a {@link Beast2SyncRangeReader}:
196
+ * through a reader the open reads only the tail (footer + index) and the
197
+ * head (header sections), and every segment read fetches exactly that
198
+ * segment's frame — a file-backed reader keeps the wire bytes in the page
199
+ * cache rather than on the heap. A Set/Dict root's first keyed read verifies
200
+ * the fences, probing a bounded prefix of every frame once (never the frame,
201
+ * unless its first key is wider than the probe); later keyed reads fetch one
202
+ * frame.
203
+ *
194
204
  * Set/Dict blobs page like Arrays: the wire holds the canonical value split
195
205
  * at segment boundaries (strictly ascending, disjoint segments), so row
196
206
  * windows ({@link slice}) and key lookups ({@link get}) address the sorted
@@ -209,7 +219,9 @@ export declare class Beast2Pages<T extends EastType = EastType> {
209
219
  readonly elementCount: number;
210
220
  /** Whether segments are independently decodable. */
211
221
  readonly selfContained: boolean;
212
- private readonly data;
222
+ private readonly source;
223
+ /** Wire offset of the terminator frame — where the last segment's frame ends. */
224
+ private readonly segmentsEnd;
213
225
  private readonly indexData;
214
226
  private readonly kind;
215
227
  private readonly typeValue;
@@ -230,9 +242,14 @@ export declare class Beast2Pages<T extends EastType = EastType> {
230
242
  * container walk. */
231
243
  private readonly segmentCache;
232
244
  /** @internal Use {@link openBeast2PagesFor}. */
233
- constructor(data: Uint8Array, typeValue: EastTypeValue, options?: Beast2DecodeOptions);
245
+ constructor(source: Uint8Array | Beast2SyncRangeReader, typeValue: EastTypeValue, options?: Beast2DecodeOptions);
234
246
  /** Number of segments in the blob. */
235
247
  get segmentCount(): number;
248
+ /** Reads segment `i`'s frame — exactly its wire bytes, from its index
249
+ * offset to the next segment's (or the terminator) — and opens its
250
+ * logical chunk. The only place segment bytes are fetched, so a ranged
251
+ * source touches one frame per decode. */
252
+ private frameReader;
236
253
  /**
237
254
  * Decodes one segment by index.
238
255
  *
@@ -256,7 +273,10 @@ export declare class Beast2Pages<T extends EastType = EastType> {
256
273
  * only — see {@link segmentCache}. */
257
274
  private segmentCached;
258
275
  /** Decodes just the first key/element of segment `i` — a bounded probe
259
- * (one frame inflate, one element decode), not a whole-segment decode. */
276
+ * (a prefix of the frame read and inflated, one element decode), not a
277
+ * whole-segment decode. A first key wider than the probe grows it; the
278
+ * final attempt reads the frame whole, so corruption is still reported
279
+ * with the frame's own error. */
260
280
  private firstKey;
261
281
  /**
262
282
  * Probes segment `i`'s fence: its first Dict key, Set element, or Array
@@ -326,13 +346,17 @@ export declare class Beast2Pages<T extends EastType = EastType> {
326
346
  get(key: ValueTypeOf<T> extends Map<infer K, any> ? K : ValueTypeOf<T> extends Set<infer E> ? E : never): (ValueTypeOf<T> extends Map<any, infer V> ? V : ValueTypeOf<T> extends Set<infer E> ? E : never) | undefined;
327
347
  }
328
348
  /**
329
- * Builds a curried pages opener: `open(data)` parses the header, footer and
349
+ * Builds a curried pages opener: `open(source)` parses the header, footer and
330
350
  * index once and returns a {@link Beast2Pages} for random access.
331
351
  *
352
+ * `source` is the whole blob, or a {@link Beast2SyncRangeReader} over it —
353
+ * then only the tail, the head and the segments actually read are ever
354
+ * fetched.
355
+ *
332
356
  * @param type - the collection type (Array/Set/Dict)
333
357
  * @param options - decode options (platform functions for decoded functions)
334
358
  * @returns a function opening a blob for paged reads
335
359
  * @throws {TypeError} When `type` is not an Array, Set or Dict type.
336
360
  */
337
- export declare function openBeast2PagesFor<T extends EastType>(type: T | EastTypeValue, options?: Beast2DecodeOptions): (data: Uint8Array) => Beast2Pages<T>;
361
+ export declare function openBeast2PagesFor<T extends EastType>(type: T | EastTypeValue, options?: Beast2DecodeOptions): (source: Uint8Array | Beast2SyncRangeReader) => Beast2Pages<T>;
338
362
  //# sourceMappingURL=stream.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../../../../src/serialization/beast2/v5/stream.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../../../../src/serialization/beast2/v5/stream.ts"],"names":[],"mappings":"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"}
@@ -28,8 +28,9 @@ import { SortedSet } from "../../../containers/sortedset.js";
28
28
  import { SortedMap } from "../../../containers/sortedmap.js";
29
29
  import { buildPlatformContext } from "../shared.js";
30
30
  import { writeTypeSection, readTypeSection, asTypeValue } from "./type-section.js";
31
- import { FrameReader, writeFrame } from "./frames.js";
31
+ import { FrameReader, openFramePrefix, writeFrame } from "./frames.js";
32
32
  import { MAGIC_BYTES_V5, TAG_NEW, createV5EncodeContext, buildV5Encoder, buildV5Decoder, writeSourceMapSectionV5, readSourceMapSectionV5, writeIndexAndFooter, readIndex, isSegmentedRoot, } from "./codec.js";
33
+ import { TAG_OR_TERMINATOR_FRAME, bytesReader, isBeast2SyncRangeReader, readExact, readU64LE, readBeast2ExtentsSync } from "./range.js";
33
34
  /** Validates that a root type is streamable and returns its kind. */
34
35
  function checkSegmented(typeValue) {
35
36
  if (!isSegmentedRoot(typeValue)) {
@@ -537,6 +538,11 @@ export function iterBeast2SegmentsFor(type, options) {
537
538
  * of once per element. Bounded — at most this many decoded segments live
538
539
  * per reader. */
539
540
  const SEGMENT_CACHE_CAPACITY = 4;
541
+ /** The bytes a fence probe reads first: the frame header plus enough of the
542
+ * payload for the first key of any ordinary row. A key that does not fit
543
+ * grows the probe fourfold until it does, the final attempt reading the
544
+ * frame whole (mirrors east-c's probe). */
545
+ const FENCE_PROBE_BYTES = 4096;
540
546
  /**
541
547
  * Random access over an indexed, self-contained v5 collection blob.
542
548
  *
@@ -548,6 +554,15 @@ const SEGMENT_CACHE_CAPACITY = 4;
548
554
  * small LRU, so a read loop over neighbouring rows decodes each segment once
549
555
  * rather than once per element; {@link segment} itself always decodes fresh.
550
556
  *
557
+ * The blob is either a whole `Uint8Array` or a {@link Beast2SyncRangeReader}:
558
+ * through a reader the open reads only the tail (footer + index) and the
559
+ * head (header sections), and every segment read fetches exactly that
560
+ * segment's frame — a file-backed reader keeps the wire bytes in the page
561
+ * cache rather than on the heap. A Set/Dict root's first keyed read verifies
562
+ * the fences, probing a bounded prefix of every frame once (never the frame,
563
+ * unless its first key is wider than the probe); later keyed reads fetch one
564
+ * frame.
565
+ *
551
566
  * Set/Dict blobs page like Arrays: the wire holds the canonical value split
552
567
  * at segment boundaries (strictly ascending, disjoint segments), so row
553
568
  * windows ({@link slice}) and key lookups ({@link get}) address the sorted
@@ -566,7 +581,9 @@ export class Beast2Pages {
566
581
  elementCount;
567
582
  /** Whether segments are independently decodable. */
568
583
  selfContained;
569
- data;
584
+ source;
585
+ /** Wire offset of the terminator frame — where the last segment's frame ends. */
586
+ segmentsEnd;
570
587
  indexData;
571
588
  kind;
572
589
  typeValue;
@@ -587,14 +604,31 @@ export class Beast2Pages {
587
604
  * container walk. */
588
605
  segmentCache = new Map();
589
606
  /** @internal Use {@link openBeast2PagesFor}. */
590
- constructor(data, typeValue, options) {
591
- const { kind, sourceMap, frameOffset } = openSegmented(data, typeValue);
592
- void frameOffset;
593
- const index = readIndex(data);
594
- if (!index) {
595
- throw new Error(`beast2 v5: blob has no index/footer — paging needs a writer with index enabled`);
607
+ constructor(source, typeValue, options) {
608
+ let kind;
609
+ let sourceMap;
610
+ let index;
611
+ if (!isBeast2SyncRangeReader(source)) {
612
+ ({ kind, sourceMap } = openSegmented(source, typeValue));
613
+ const whole = readIndex(source);
614
+ if (!whole) {
615
+ throw new Error(`beast2 v5: blob has no index/footer — paging needs a writer with index enabled`);
616
+ }
617
+ index = whole;
618
+ // readIndex validated the footer, so the u64 before its magic is the
619
+ // index offset; the terminator frame sits directly ahead of it.
620
+ this.segmentsEnd = readU64LE(source, source.length - 16) - TAG_OR_TERMINATOR_FRAME.length;
621
+ this.source = bytesReader(source);
622
+ }
623
+ else {
624
+ // Two positioned reads — the tail, then the head — give the whole
625
+ // geometry; the segment frames are read one at a time from here on.
626
+ const extents = readBeast2ExtentsSync(source);
627
+ ({ kind, sourceMap } = openSegmented(extents.head, typeValue));
628
+ index = { selfContained: extents.selfContained, offsets: [...extents.offsets], counts: [...extents.counts], totalCount: extents.elementCount };
629
+ this.segmentsEnd = extents.segmentsEnd;
630
+ this.source = source;
596
631
  }
597
- this.data = data;
598
632
  this.indexData = index;
599
633
  this.kind = kind;
600
634
  this.typeValue = typeValue;
@@ -616,6 +650,15 @@ export class Beast2Pages {
616
650
  get segmentCount() {
617
651
  return this.indexData.offsets.length;
618
652
  }
653
+ /** Reads segment `i`'s frame — exactly its wire bytes, from its index
654
+ * offset to the next segment's (or the terminator) — and opens its
655
+ * logical chunk. The only place segment bytes are fetched, so a ranged
656
+ * source touches one frame per decode. */
657
+ frameReader(i) {
658
+ const start = this.indexData.offsets[i];
659
+ const end = i + 1 < this.indexData.offsets.length ? this.indexData.offsets[i + 1] : this.segmentsEnd;
660
+ return new FrameReader(readExact(this.source, start, end - start), 0).next();
661
+ }
619
662
  /**
620
663
  * Decodes one segment by index.
621
664
  *
@@ -641,8 +684,7 @@ export class Beast2Pages {
641
684
  if (i < 0 || i >= this.indexData.offsets.length) {
642
685
  throw new Error(`beast2 v5: segment ${i} out of range (${this.indexData.offsets.length} segments)`);
643
686
  }
644
- const cursor = new FrameReader(this.data, this.indexData.offsets[i]);
645
- const reader = cursor.next();
687
+ const reader = this.frameReader(i);
646
688
  const n = reader.readVarint();
647
689
  if (n !== this.indexData.counts[i]) {
648
690
  throw new Error(`beast2 v5: segment ${i} declares ${n} elements, index says ${this.indexData.counts[i]}`);
@@ -689,17 +731,38 @@ export class Beast2Pages {
689
731
  return seg;
690
732
  }
691
733
  /** Decodes just the first key/element of segment `i` — a bounded probe
692
- * (one frame inflate, one element decode), not a whole-segment decode. */
734
+ * (a prefix of the frame read and inflated, one element decode), not a
735
+ * whole-segment decode. A first key wider than the probe grows it; the
736
+ * final attempt reads the frame whole, so corruption is still reported
737
+ * with the frame's own error. */
693
738
  firstKey(i) {
694
739
  if (!this.fenceDec) {
695
740
  const keyType = this.kind === "Dict" ? this.typeValue.value.key : this.typeValue.value;
696
741
  this.fenceDec = buildV5Decoder(keyType);
697
742
  }
698
- const cursor = new FrameReader(this.data, this.indexData.offsets[i]);
699
- const reader = cursor.next();
700
- reader.readVarint(); // element count — segments are never empty
701
- const ctx = { containers: [], sourceMap: this.sourceMap, frozen: this.platform?.frozen ?? false, ...buildPlatformContext(this.platform) };
702
- return this.fenceDec(reader, ctx);
743
+ const start = this.indexData.offsets[i];
744
+ const end = i + 1 < this.indexData.offsets.length ? this.indexData.offsets[i + 1] : this.segmentsEnd;
745
+ const frameLen = end - start;
746
+ for (let probe = Math.min(frameLen, FENCE_PROBE_BYTES);; probe = Math.min(frameLen, probe * 4)) {
747
+ const whole = probe === frameLen;
748
+ const bytes = readExact(this.source, start, probe);
749
+ const ctx = { containers: [], sourceMap: this.sourceMap, frozen: this.platform?.frozen ?? false, ...buildPlatformContext(this.platform) };
750
+ if (whole) {
751
+ const reader = new FrameReader(bytes, 0).next();
752
+ reader.readVarint(); // element count — segments are never empty
753
+ return this.fenceDec(reader, ctx);
754
+ }
755
+ try {
756
+ const reader = openFramePrefix(bytes);
757
+ if (reader !== null) {
758
+ reader.readVarint();
759
+ return this.fenceDec(reader, ctx);
760
+ }
761
+ }
762
+ catch {
763
+ // Short, or corrupt: more of the frame decides which.
764
+ }
765
+ }
703
766
  }
704
767
  /**
705
768
  * Probes segment `i`'s fence: its first Dict key, Set element, or Array
@@ -914,9 +977,13 @@ export class Beast2Pages {
914
977
  }
915
978
  }
916
979
  /**
917
- * Builds a curried pages opener: `open(data)` parses the header, footer and
980
+ * Builds a curried pages opener: `open(source)` parses the header, footer and
918
981
  * index once and returns a {@link Beast2Pages} for random access.
919
982
  *
983
+ * `source` is the whole blob, or a {@link Beast2SyncRangeReader} over it —
984
+ * then only the tail, the head and the segments actually read are ever
985
+ * fetched.
986
+ *
920
987
  * @param type - the collection type (Array/Set/Dict)
921
988
  * @param options - decode options (platform functions for decoded functions)
922
989
  * @returns a function opening a blob for paged reads
@@ -925,6 +992,6 @@ export class Beast2Pages {
925
992
  export function openBeast2PagesFor(type, options) {
926
993
  const typeValue = asTypeValue(type);
927
994
  checkSegmented(typeValue);
928
- return (data) => new Beast2Pages(data, typeValue, options);
995
+ return (source) => new Beast2Pages(source, typeValue, options);
929
996
  }
930
997
  //# sourceMappingURL=stream.js.map