@bldrs-ai/conway 1.399.1223 → 1.401.1237
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/compiled/Dist/ConwayGeomWasmNode.js +0 -0
- package/compiled/Dist/ConwayGeomWasmNodeMT.js +0 -0
- package/compiled/Dist/ConwayGeomWasmWeb.js +0 -0
- package/compiled/Dist/ConwayGeomWasmWebMT.js +1 -1
- package/compiled/Dist/ConwayGeomWasmWebMT.wasm +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNode.js +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNodeMT.js +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWeb.js +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWebMT.js +1 -1
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWebMT.wasm +0 -0
- package/compiled/examples/browser-bundled.cjs +184 -11
- package/compiled/examples/cli-bundled.cjs +213 -40
- package/compiled/examples/cli-step-bundled.cjs +105 -37
- package/compiled/examples/validator-bundled.cjs +184 -11
- package/compiled/src/ifc/ifc_step_model.d.ts +5 -2
- package/compiled/src/ifc/ifc_step_model.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_step_model.js +5 -3
- package/compiled/src/ifc/ifc_step_parser.d.ts +36 -0
- package/compiled/src/ifc/ifc_step_parser.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_step_parser.js +40 -0
- package/compiled/src/ifc/ifc_stream_model.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_stream_model.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_stream_model.test.js +70 -0
- package/compiled/src/parsing/parsing_buffer.d.ts +23 -0
- package/compiled/src/parsing/parsing_buffer.d.ts.map +1 -1
- package/compiled/src/parsing/parsing_buffer.js +31 -0
- package/compiled/src/step/parsing/byte_source.d.ts +55 -0
- package/compiled/src/step/parsing/byte_source.d.ts.map +1 -0
- package/compiled/src/step/parsing/byte_source.js +35 -0
- package/compiled/src/step/parsing/incremental_type_index.d.ts +64 -0
- package/compiled/src/step/parsing/incremental_type_index.d.ts.map +1 -0
- package/compiled/src/step/parsing/incremental_type_index.js +92 -0
- package/compiled/src/step/parsing/incremental_type_index.test.d.ts +2 -0
- package/compiled/src/step/parsing/incremental_type_index.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/incremental_type_index.test.js +55 -0
- package/compiled/src/step/parsing/step_parser.d.ts +19 -0
- package/compiled/src/step/parsing/step_parser.d.ts.map +1 -1
- package/compiled/src/step/parsing/step_parser.js +48 -4
- package/compiled/src/step/parsing/streaming_index_builder.d.ts +70 -0
- package/compiled/src/step/parsing/streaming_index_builder.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_index_builder.js +125 -0
- package/compiled/src/step/parsing/streaming_index_builder.test.d.ts +2 -0
- package/compiled/src/step/parsing/streaming_index_builder.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_index_builder.test.js +107 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts +55 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.js +67 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.test.d.ts +2 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.test.js +66 -0
- package/compiled/src/step/step_model_base.d.ts +9 -3
- package/compiled/src/step/step_model_base.d.ts.map +1 -1
- package/compiled/src/step/step_model_base.js +9 -3
- package/compiled/src/version/version.js +1 -1
- package/compiled/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -944,7 +944,7 @@ var EntityTypesIfcCount = 909;
|
|
|
944
944
|
var entity_types_ifc_gen_default = EntityTypesIfc;
|
|
945
945
|
|
|
946
946
|
// compiled/src/version/version.js
|
|
947
|
-
var versionString = "Conway v1.
|
|
947
|
+
var versionString = "Conway v1.401.1237";
|
|
948
948
|
|
|
949
949
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
950
950
|
var wasmType = "";
|
|
@@ -2200,6 +2200,37 @@ var ParsingBuffer = class {
|
|
|
2200
2200
|
this.buffer = buffer;
|
|
2201
2201
|
this.end = endOffset;
|
|
2202
2202
|
}
|
|
2203
|
+
/**
|
|
2204
|
+
* Streaming support: repoint this buffer at a fresh window over the same
|
|
2205
|
+
* logical stream while keeping `address` file-absolute.
|
|
2206
|
+
*
|
|
2207
|
+
* A moving-window parse holds only a slice of the source in memory at a
|
|
2208
|
+
* time. Between top-level records (where the rewind stack is empty) the
|
|
2209
|
+
* driver slides the window forward: it copies the unconsumed tail to the
|
|
2210
|
+
* front of a reused buffer, appends freshly-read bytes, and calls this to
|
|
2211
|
+
* repoint the parser. `addressBase` is the file offset that window index 0
|
|
2212
|
+
* now corresponds to; we store it as a negative initial offset so
|
|
2213
|
+
* `address` ( = cursor − initialOffset ) stays the file-absolute value the
|
|
2214
|
+
* non-streaming parse would have produced.
|
|
2215
|
+
*
|
|
2216
|
+
* Must only be called with the rewind stack empty (i.e. at a record
|
|
2217
|
+
* boundary) — the stack holds window-relative cursors that a slide would
|
|
2218
|
+
* invalidate. Throws otherwise.
|
|
2219
|
+
*
|
|
2220
|
+
* @param buffer The new window buffer.
|
|
2221
|
+
* @param cursorInWindow The cursor position within the new window.
|
|
2222
|
+
* @param endInWindow The count of valid bytes in the new window.
|
|
2223
|
+
* @param addressBase The file offset that window index 0 maps to.
|
|
2224
|
+
*/
|
|
2225
|
+
rebaseWindow(buffer, cursorInWindow, endInWindow, addressBase) {
|
|
2226
|
+
if (this.rewindStack_.length !== 0) {
|
|
2227
|
+
throw Error("rebaseWindow called mid-transaction (rewind stack non-empty)");
|
|
2228
|
+
}
|
|
2229
|
+
this.buffer = buffer;
|
|
2230
|
+
this.cursor_ = cursorInWindow;
|
|
2231
|
+
this.initialOffset_ = -addressBase;
|
|
2232
|
+
this.end = endInWindow;
|
|
2233
|
+
}
|
|
2203
2234
|
/**
|
|
2204
2235
|
* Construct this with a buffer, initial offset into the buffer and an end offset.
|
|
2205
2236
|
*
|
|
@@ -3452,6 +3483,34 @@ var StepParser = class extends StepHeaderParser {
|
|
|
3452
3483
|
onProgress?.(next.value);
|
|
3453
3484
|
}
|
|
3454
3485
|
}
|
|
3486
|
+
/**
|
|
3487
|
+
* Streaming driver over parseDataBlockIncremental: identical parse (same
|
|
3488
|
+
* generator body) but invokes `onRecordBoundary` at every top-level record
|
|
3489
|
+
* boundary so a caller feeding the parser from a moving window can slide
|
|
3490
|
+
* that window forward while the rewind stack is empty. See
|
|
3491
|
+
* streaming_index_builder.ts for the coordinator that owns the window.
|
|
3492
|
+
*
|
|
3493
|
+
* @param input The input parsing buffer, positioned at the data section.
|
|
3494
|
+
* @param onRecordBoundary Called at each top-level record boundary with the
|
|
3495
|
+
* buffer; the callback may rebase the buffer's window in place.
|
|
3496
|
+
* @param onRecordIndexed Called as each top-level record is indexed, with
|
|
3497
|
+
* its localID, expressID and typeID (0 for external-mapping records) — the
|
|
3498
|
+
* seam for incremental semantic consumers (type index, roots registry,
|
|
3499
|
+
* names skeleton). Must be synchronous and cheap; expensive work belongs on
|
|
3500
|
+
* a demand queue, not the parse path.
|
|
3501
|
+
* @param onProgress Optional byte-cursor progress callback.
|
|
3502
|
+
* @return {BlockParseResult} The parsing result, including the index and result enum.
|
|
3503
|
+
*/
|
|
3504
|
+
parseDataBlockStreamed(input, onRecordBoundary, onRecordIndexed, onProgress) {
|
|
3505
|
+
const parser211 = this.parseDataBlockIncremental(input, onRecordBoundary, onRecordIndexed);
|
|
3506
|
+
while (true) {
|
|
3507
|
+
const next = parser211.next();
|
|
3508
|
+
if (next.done === true) {
|
|
3509
|
+
return next.value;
|
|
3510
|
+
}
|
|
3511
|
+
onProgress?.(next.value);
|
|
3512
|
+
}
|
|
3513
|
+
}
|
|
3455
3514
|
/**
|
|
3456
3515
|
* Cooperative variant of parseDataBlock: identical parse (same generator
|
|
3457
3516
|
* body), but periodically awaits a macrotask so the event loop can run —
|
|
@@ -3489,7 +3548,7 @@ var StepParser = class extends StepHeaderParser {
|
|
|
3489
3548
|
* @yields {number} The current byte cursor within the input buffer.
|
|
3490
3549
|
* @return {BlockParseResult} The parsing result, including the index and result enum.
|
|
3491
3550
|
*/
|
|
3492
|
-
*parseDataBlockIncremental(input) {
|
|
3551
|
+
*parseDataBlockIncremental(input, onRecordBoundary, onRecordIndexed) {
|
|
3493
3552
|
const indexResult = { elements: [] };
|
|
3494
3553
|
const match = input.match;
|
|
3495
3554
|
const comment = () => match(commentParser2);
|
|
@@ -3536,7 +3595,7 @@ var StepParser = class extends StepHeaderParser {
|
|
|
3536
3595
|
return syntaxError();
|
|
3537
3596
|
}
|
|
3538
3597
|
whitespace();
|
|
3539
|
-
const startElement = input.
|
|
3598
|
+
const startElement = input.address;
|
|
3540
3599
|
let stackDepth = 1;
|
|
3541
3600
|
const savedInlineElements = inlineElements;
|
|
3542
3601
|
inlineElements = void 0;
|
|
@@ -3630,6 +3689,7 @@ var StepParser = class extends StepHeaderParser {
|
|
|
3630
3689
|
if ((++parsedElementCount & PARSE_PROGRESS_ELEMENT_MASK) === 0) {
|
|
3631
3690
|
yield input.cursor;
|
|
3632
3691
|
}
|
|
3692
|
+
onRecordBoundary?.(input);
|
|
3633
3693
|
if (!charws(HASH2)) {
|
|
3634
3694
|
if (tokenws(END_SECTION)) {
|
|
3635
3695
|
return parseResult2(ParseResult.COMPLETE);
|
|
@@ -3652,7 +3712,7 @@ var StepParser = class extends StepHeaderParser {
|
|
|
3652
3712
|
}
|
|
3653
3713
|
whitespace();
|
|
3654
3714
|
inlineElements = void 0;
|
|
3655
|
-
const startElement2 = input.
|
|
3715
|
+
const startElement2 = input.address;
|
|
3656
3716
|
while (!charws(CLOSE_PAREN2)) {
|
|
3657
3717
|
input.begin();
|
|
3658
3718
|
const elementResult = parseInlineElement(expressID);
|
|
@@ -3665,6 +3725,7 @@ var StepParser = class extends StepHeaderParser {
|
|
|
3665
3725
|
if (!charws(SEMICOLON)) {
|
|
3666
3726
|
return syntaxError();
|
|
3667
3727
|
}
|
|
3728
|
+
onRecordIndexed?.(indexResult.elements.length, expressID, 0);
|
|
3668
3729
|
indexResult.elements.push({
|
|
3669
3730
|
address: startElement2,
|
|
3670
3731
|
length: input.address - startElement2,
|
|
@@ -3683,7 +3744,7 @@ var StepParser = class extends StepHeaderParser {
|
|
|
3683
3744
|
return syntaxError();
|
|
3684
3745
|
}
|
|
3685
3746
|
whitespace();
|
|
3686
|
-
const startElement = input.
|
|
3747
|
+
const startElement = input.address;
|
|
3687
3748
|
let stackDepth = 1;
|
|
3688
3749
|
inlineElements = void 0;
|
|
3689
3750
|
while (stackDepth > 0) {
|
|
@@ -3756,6 +3817,7 @@ var StepParser = class extends StepHeaderParser {
|
|
|
3756
3817
|
if (!charws(SEMICOLON)) {
|
|
3757
3818
|
return syntaxError();
|
|
3758
3819
|
}
|
|
3820
|
+
onRecordIndexed?.(indexResult.elements.length, expressID, foundItem);
|
|
3759
3821
|
indexResult.elements.push({
|
|
3760
3822
|
address: startElement,
|
|
3761
3823
|
length: input.address - startElement,
|
|
@@ -4918,18 +4980,24 @@ var StepModelBase = class {
|
|
|
4918
4980
|
* Construct this step model with its matching schema, a buffer to read from and an element index.
|
|
4919
4981
|
*
|
|
4920
4982
|
* @param schema The Step schema this is based on.
|
|
4921
|
-
* @param buffer_ The buffer to read this from.
|
|
4983
|
+
* @param buffer_ The buffer to read this from. Pass `undefined` together
|
|
4984
|
+
* with `provider` to build a model whose source is windowed from
|
|
4985
|
+
* construction (e.g. a streaming open — see buildModelStreaming); the
|
|
4986
|
+
* synchronous read paths (geometry extraction) then require the relevant
|
|
4987
|
+
* ranges to be resident, exactly as after `spillSourceToExternalStore`.
|
|
4922
4988
|
* @param elementIndex The element index for this, parsed or deserialized - note this takes
|
|
4923
4989
|
* ownership of this array in the sense it will modify values/unfold inline elements etc.
|
|
4990
|
+
* @param provider Optional pre-built buffer provider. When omitted, a
|
|
4991
|
+
* resident provider over `buffer_` is used (the classic path).
|
|
4924
4992
|
*/
|
|
4925
|
-
constructor(schema, buffer_, elementIndex) {
|
|
4993
|
+
constructor(schema, buffer_, elementIndex, provider) {
|
|
4926
4994
|
this.schema = schema;
|
|
4927
4995
|
this.buffer_ = buffer_;
|
|
4928
4996
|
this.vtableBuilder_ = new StepVtableBuilder();
|
|
4929
4997
|
this.descriptorCache_ = [];
|
|
4930
4998
|
this.elementMemoization = true;
|
|
4931
4999
|
this.nullOnErrors = true;
|
|
4932
|
-
this.bufferProvider_ = new ResidentStepBufferProvider(buffer_);
|
|
5000
|
+
this.bufferProvider_ = provider ?? new ResidentStepBufferProvider(buffer_);
|
|
4933
5001
|
const localElementIndex = elementIndex;
|
|
4934
5002
|
let where = 0;
|
|
4935
5003
|
const firstInlineElement = localElementIndex.length;
|
|
@@ -70692,11 +70760,13 @@ var IfcStepModel = class extends StepModelBase {
|
|
|
70692
70760
|
* Construct this model given a buffer containing the data and the parsed data index on that,
|
|
70693
70761
|
* adding the typeIndex on top of that.
|
|
70694
70762
|
*
|
|
70695
|
-
* @param buffer The buffer to values from
|
|
70763
|
+
* @param buffer The buffer to values from, or `undefined` with `provider`
|
|
70764
|
+
* set for a windowed (streaming) source.
|
|
70696
70765
|
* @param elementIndex The parsed index to elements in the STEP.
|
|
70766
|
+
* @param provider Optional pre-built buffer provider (windowed source).
|
|
70697
70767
|
*/
|
|
70698
|
-
constructor(buffer, elementIndex) {
|
|
70699
|
-
super(schema_ifc_gen_default, buffer, elementIndex);
|
|
70768
|
+
constructor(buffer, elementIndex, provider) {
|
|
70769
|
+
super(schema_ifc_gen_default, buffer, elementIndex, provider);
|
|
70700
70770
|
this.externalMappingType = ifc_step_external_mapping_default;
|
|
70701
70771
|
this.geometry = new IfcModelGeometry(this);
|
|
70702
70772
|
this.voidGeometry = new IfcModelGeometry(this, true);
|
|
@@ -70710,7 +70780,76 @@ var IfcStepModel = class extends StepModelBase {
|
|
|
70710
70780
|
}
|
|
70711
70781
|
};
|
|
70712
70782
|
|
|
70783
|
+
// compiled/src/step/parsing/streaming_index_builder.js
|
|
70784
|
+
function buildIndexStreaming(source, parser211, pool3, onRecordIndexed) {
|
|
70785
|
+
const fileSize = source.byteLength;
|
|
70786
|
+
let windowBytes = Math.max(pool3, MIN_WINDOW);
|
|
70787
|
+
for (; ; ) {
|
|
70788
|
+
const window2 = new Uint8Array(windowBytes);
|
|
70789
|
+
let windowStartFile = 0;
|
|
70790
|
+
let windowLen = source.read(0, windowBytes, window2, 0);
|
|
70791
|
+
let bytesRead = windowLen;
|
|
70792
|
+
const input = new ParsingBuffer(window2, 0, windowLen);
|
|
70793
|
+
const [header, headerResult] = parser211.parseHeader(input);
|
|
70794
|
+
if (headerResult !== ParseResult.COMPLETE) {
|
|
70795
|
+
return {
|
|
70796
|
+
header,
|
|
70797
|
+
elements: [],
|
|
70798
|
+
result: headerResult,
|
|
70799
|
+
stats: { pool: pool3, windowBytes, slides: 0, maxRecordLen: 0, bytesRead }
|
|
70800
|
+
};
|
|
70801
|
+
}
|
|
70802
|
+
const slideThreshold = windowBytes >> 1;
|
|
70803
|
+
let slides = 0;
|
|
70804
|
+
let maxRecordLen = 0;
|
|
70805
|
+
let prevBoundaryFile = windowStartFile + input.cursor;
|
|
70806
|
+
const onRecordBoundary = (buffer) => {
|
|
70807
|
+
const cursor = buffer.cursor;
|
|
70808
|
+
const recordFileStart = windowStartFile + cursor;
|
|
70809
|
+
const recordLen = recordFileStart - prevBoundaryFile;
|
|
70810
|
+
if (recordLen > maxRecordLen) {
|
|
70811
|
+
maxRecordLen = recordLen;
|
|
70812
|
+
}
|
|
70813
|
+
prevBoundaryFile = recordFileStart;
|
|
70814
|
+
if (windowStartFile + windowLen >= fileSize) {
|
|
70815
|
+
return;
|
|
70816
|
+
}
|
|
70817
|
+
if (cursor < slideThreshold) {
|
|
70818
|
+
return;
|
|
70819
|
+
}
|
|
70820
|
+
const tail = windowLen - cursor;
|
|
70821
|
+
window2.copyWithin(0, cursor, windowLen);
|
|
70822
|
+
const want = windowBytes - tail;
|
|
70823
|
+
const got = source.read(windowStartFile + windowLen, want, window2, tail);
|
|
70824
|
+
bytesRead += got;
|
|
70825
|
+
windowLen = tail + got;
|
|
70826
|
+
windowStartFile = recordFileStart;
|
|
70827
|
+
buffer.rebaseWindow(window2, 0, windowLen, windowStartFile);
|
|
70828
|
+
++slides;
|
|
70829
|
+
};
|
|
70830
|
+
const [index, result] = parser211.parseDataBlockStreamed(input, onRecordBoundary, onRecordIndexed);
|
|
70831
|
+
const stoppedShort = result !== ParseResult.COMPLETE;
|
|
70832
|
+
const notAtEof = windowStartFile + windowLen < fileSize;
|
|
70833
|
+
if (stoppedShort && notAtEof) {
|
|
70834
|
+
windowBytes *= 2;
|
|
70835
|
+
continue;
|
|
70836
|
+
}
|
|
70837
|
+
const lastRecordLen = windowStartFile + input.cursor - prevBoundaryFile;
|
|
70838
|
+
if (lastRecordLen > maxRecordLen) {
|
|
70839
|
+
maxRecordLen = lastRecordLen;
|
|
70840
|
+
}
|
|
70841
|
+
return {
|
|
70842
|
+
header,
|
|
70843
|
+
elements: index.elements,
|
|
70844
|
+
result,
|
|
70845
|
+
stats: { pool: pool3, windowBytes, slides, maxRecordLen, bytesRead }
|
|
70846
|
+
};
|
|
70847
|
+
}
|
|
70848
|
+
}
|
|
70849
|
+
var MIN_WINDOW = 4 * 1024;
|
|
70850
|
+
|
|
70713
70851
|
// compiled/src/ifc/ifc_step_parser.js
|
|
70852
|
+
var DEFAULT_STREAM_POOL_BYTES = 1024 * 1024;
|
|
70714
70853
|
var IfcStepParser = class extends StepParser {
|
|
70715
70854
|
/**
|
|
70716
70855
|
* Construct the IFC step parser.
|
|
@@ -70743,6 +70882,40 @@ var IfcStepParser = class extends StepParser {
|
|
|
70743
70882
|
const [itemIndex, parseResult2] = await this.parseDataBlockAsync(input, onProgress);
|
|
70744
70883
|
return [parseResult2, new IfcStepModel(input.buffer, itemIndex.elements)];
|
|
70745
70884
|
}
|
|
70885
|
+
/**
|
|
70886
|
+
* Build a model by streaming the source through a bounded moving window
|
|
70887
|
+
* (see buildIndexStreaming / M0) rather than parsing one resident buffer,
|
|
70888
|
+
* then backing the model with a windowed provider over `store` — so the
|
|
70889
|
+
* source is never held fully resident in the JS heap.
|
|
70890
|
+
*
|
|
70891
|
+
* `source` serves the parse (synchronous windowed reads — on a worker this
|
|
70892
|
+
* is an OPFS sync-access handle; in node/tests a file descriptor or buffer)
|
|
70893
|
+
* and `store` serves the model's post-parse property access (asynchronous
|
|
70894
|
+
* windowed reads paged in on demand — OPFS `File.slice()` in the browser).
|
|
70895
|
+
* Both view the same file bytes, so the file-absolute addresses the index
|
|
70896
|
+
* records resolve identically through either.
|
|
70897
|
+
*
|
|
70898
|
+
* NOTE (M1 scope): this delivers the bounded-memory *parse*. Synchronous
|
|
70899
|
+
* geometry extraction still needs its record ranges resident — as after
|
|
70900
|
+
* `spillSourceToExternalStore` — so a caller that extracts geometry must
|
|
70901
|
+
* `ensureResident` first (demand-driven geometry is M3). Property / index
|
|
70902
|
+
* access works directly via the async surfaces.
|
|
70903
|
+
*
|
|
70904
|
+
* @param source Synchronous byte source feeding the streaming parse.
|
|
70905
|
+
* @param store Async external store backing the windowed model.
|
|
70906
|
+
* @param opts Optional window sizing: `pool` (parse window),
|
|
70907
|
+
* `chunkBytes` / `maxResidentChunks` (model window).
|
|
70908
|
+
* @return {[ParseResult, IfcStepModel | undefined]} The parse result and
|
|
70909
|
+
* the windowed model.
|
|
70910
|
+
*/
|
|
70911
|
+
parseStreamToModel(source, store, opts) {
|
|
70912
|
+
if (store.byteLength !== source.byteLength) {
|
|
70913
|
+
throw new Error(`Streaming store byteLength ${store.byteLength} does not match source byteLength ${source.byteLength}`);
|
|
70914
|
+
}
|
|
70915
|
+
const { elements, result } = buildIndexStreaming(source, this, opts?.pool ?? DEFAULT_STREAM_POOL_BYTES);
|
|
70916
|
+
const provider = new WindowedStepBufferProvider(store, opts?.chunkBytes, opts?.maxResidentChunks);
|
|
70917
|
+
return [result, new IfcStepModel(void 0, elements, provider)];
|
|
70918
|
+
}
|
|
70746
70919
|
};
|
|
70747
70920
|
IfcStepParser.Instance = new IfcStepParser();
|
|
70748
70921
|
var ifc_step_parser_default = IfcStepParser;
|
|
@@ -8,6 +8,7 @@ import IfcStepExternalMapping from "./ifc_step_external_mapping.js";
|
|
|
8
8
|
import IfcModelCurves from "./ifc_model_curves.js";
|
|
9
9
|
import { CsgMemoization } from "../core/csg_operations.js";
|
|
10
10
|
import { IfcMaterialCache } from "./ifc_material_cache.js";
|
|
11
|
+
import { StepBufferProvider } from "../step/step_buffer_provider.js";
|
|
11
12
|
/**
|
|
12
13
|
* Represents an IFC model deserialized from step.
|
|
13
14
|
*/
|
|
@@ -26,9 +27,11 @@ export default class IfcStepModel extends StepModelBase<EntityTypesIfc> {
|
|
|
26
27
|
* Construct this model given a buffer containing the data and the parsed data index on that,
|
|
27
28
|
* adding the typeIndex on top of that.
|
|
28
29
|
*
|
|
29
|
-
* @param buffer The buffer to values from
|
|
30
|
+
* @param buffer The buffer to values from, or `undefined` with `provider`
|
|
31
|
+
* set for a windowed (streaming) source.
|
|
30
32
|
* @param elementIndex The parsed index to elements in the STEP.
|
|
33
|
+
* @param provider Optional pre-built buffer provider (windowed source).
|
|
31
34
|
*/
|
|
32
|
-
constructor(buffer: Uint8Array, elementIndex: StepIndexEntry<EntityTypesIfc>[]);
|
|
35
|
+
constructor(buffer: Uint8Array | undefined, elementIndex: StepIndexEntry<EntityTypesIfc>[], provider?: StepBufferProvider);
|
|
33
36
|
}
|
|
34
37
|
//# sourceMappingURL=ifc_step_model.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ifc_step_model.d.ts","sourceRoot":"","sources":["../../../src/ifc/ifc_step_model.ts"],"names":[],"mappings":"AAAA,OAAO,cAAqC,MAAM,iCAAiC,CAAA;AACnF,OAAO,aAAa,MAAM,yBAAyB,CAAA;AAEnD,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAA;AAE1D,OAAO,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAA;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,sBAAsB,MAAM,6BAA6B,CAAA;AAChE,OAAO,cAAc,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"ifc_step_model.d.ts","sourceRoot":"","sources":["../../../src/ifc/ifc_step_model.ts"],"names":[],"mappings":"AAAA,OAAO,cAAqC,MAAM,iCAAiC,CAAA;AACnF,OAAO,aAAa,MAAM,yBAAyB,CAAA;AAEnD,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAA;AAE1D,OAAO,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAA;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,sBAAsB,MAAM,6BAA6B,CAAA;AAChE,OAAO,cAAc,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AAKjE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,aAAa,CAAE,cAAc,CAAE;IAEvE,SAAgB,SAAS,EAAE,aAAa,CAAE,cAAc,CAAE,CAAA;IAC1D,SAAgB,mBAAmB,gCAAyB;IAC5D,SAAgB,QAAQ,mBAA+B;IACvD,SAAgB,YAAY,mBAAqC;IACjE,SAAgB,QAAQ,kBAA4B;IACpD,SAAgB,MAAM,iBAA2B;IACjD,SAAgB,aAAa,iBAAuB;IACpD,SAAgB,SAAS,mBAA+B;IACxD,SAAgB,aAAa,mBAAqC;IAClE,SAAgB,cAAc,wBAAiB;IAE/C;;;;;;;;OAQG;gBAEC,MAAM,EAAE,UAAU,GAAG,SAAS,EAC9B,YAAY,EAAE,cAAc,CAAE,cAAc,CAAE,EAAE,EAChD,QAAQ,CAAC,EAAE,kBAAkB;CAKlC"}
|
|
@@ -17,11 +17,13 @@ export default class IfcStepModel extends StepModelBase {
|
|
|
17
17
|
* Construct this model given a buffer containing the data and the parsed data index on that,
|
|
18
18
|
* adding the typeIndex on top of that.
|
|
19
19
|
*
|
|
20
|
-
* @param buffer The buffer to values from
|
|
20
|
+
* @param buffer The buffer to values from, or `undefined` with `provider`
|
|
21
|
+
* set for a windowed (streaming) source.
|
|
21
22
|
* @param elementIndex The parsed index to elements in the STEP.
|
|
23
|
+
* @param provider Optional pre-built buffer provider (windowed source).
|
|
22
24
|
*/
|
|
23
|
-
constructor(buffer, elementIndex) {
|
|
24
|
-
super(SchemaIfc, buffer, elementIndex);
|
|
25
|
+
constructor(buffer, elementIndex, provider) {
|
|
26
|
+
super(SchemaIfc, buffer, elementIndex, provider);
|
|
25
27
|
this.externalMappingType = IfcStepExternalMapping;
|
|
26
28
|
this.geometry = new IfcModelGeometry(this);
|
|
27
29
|
this.voidGeometry = new IfcModelGeometry(this, true);
|
|
@@ -2,6 +2,8 @@ import ParsingBuffer from "../parsing/parsing_buffer.js";
|
|
|
2
2
|
import StepParser, { ParseProgressCallback, ParseResult } from "../step/parsing/step_parser.js";
|
|
3
3
|
import EntityTypesIfc from "./ifc4_gen/entity_types_ifc.gen.js";
|
|
4
4
|
import IfcStepModel from "./ifc_step_model.js";
|
|
5
|
+
import { ByteSource } from "../step/parsing/byte_source.js";
|
|
6
|
+
import { StepExternalByteStore } from "../step/step_buffer_provider.js";
|
|
5
7
|
/**
|
|
6
8
|
* Parser for taking IFC file serialized in step and turning them into a lazily parsed model.
|
|
7
9
|
*/
|
|
@@ -42,5 +44,39 @@ export default class IfcStepParser extends StepParser<EntityTypesIfc> {
|
|
|
42
44
|
ParseResult,
|
|
43
45
|
IfcStepModel | undefined
|
|
44
46
|
]>;
|
|
47
|
+
/**
|
|
48
|
+
* Build a model by streaming the source through a bounded moving window
|
|
49
|
+
* (see buildIndexStreaming / M0) rather than parsing one resident buffer,
|
|
50
|
+
* then backing the model with a windowed provider over `store` — so the
|
|
51
|
+
* source is never held fully resident in the JS heap.
|
|
52
|
+
*
|
|
53
|
+
* `source` serves the parse (synchronous windowed reads — on a worker this
|
|
54
|
+
* is an OPFS sync-access handle; in node/tests a file descriptor or buffer)
|
|
55
|
+
* and `store` serves the model's post-parse property access (asynchronous
|
|
56
|
+
* windowed reads paged in on demand — OPFS `File.slice()` in the browser).
|
|
57
|
+
* Both view the same file bytes, so the file-absolute addresses the index
|
|
58
|
+
* records resolve identically through either.
|
|
59
|
+
*
|
|
60
|
+
* NOTE (M1 scope): this delivers the bounded-memory *parse*. Synchronous
|
|
61
|
+
* geometry extraction still needs its record ranges resident — as after
|
|
62
|
+
* `spillSourceToExternalStore` — so a caller that extracts geometry must
|
|
63
|
+
* `ensureResident` first (demand-driven geometry is M3). Property / index
|
|
64
|
+
* access works directly via the async surfaces.
|
|
65
|
+
*
|
|
66
|
+
* @param source Synchronous byte source feeding the streaming parse.
|
|
67
|
+
* @param store Async external store backing the windowed model.
|
|
68
|
+
* @param opts Optional window sizing: `pool` (parse window),
|
|
69
|
+
* `chunkBytes` / `maxResidentChunks` (model window).
|
|
70
|
+
* @return {[ParseResult, IfcStepModel | undefined]} The parse result and
|
|
71
|
+
* the windowed model.
|
|
72
|
+
*/
|
|
73
|
+
parseStreamToModel(source: ByteSource, store: StepExternalByteStore, opts?: {
|
|
74
|
+
pool?: number;
|
|
75
|
+
chunkBytes?: number;
|
|
76
|
+
maxResidentChunks?: number;
|
|
77
|
+
}): [
|
|
78
|
+
ParseResult,
|
|
79
|
+
IfcStepModel | undefined
|
|
80
|
+
];
|
|
45
81
|
}
|
|
46
82
|
//# sourceMappingURL=ifc_step_parser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ifc_step_parser.d.ts","sourceRoot":"","sources":["../../../src/ifc/ifc_step_parser.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,2BAA2B,CAAA;AACrD,OAAO,UAAU,EAAE,EAAC,qBAAqB,EAAE,WAAW,EAAC,MAAM,6BAA6B,CAAA;AAC1F,OAAO,cAAc,MAAM,iCAAiC,CAAA;AAE5D,OAAO,YAAY,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"ifc_step_parser.d.ts","sourceRoot":"","sources":["../../../src/ifc/ifc_step_parser.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,2BAA2B,CAAA;AACrD,OAAO,UAAU,EAAE,EAAC,qBAAqB,EAAE,WAAW,EAAC,MAAM,6BAA6B,CAAA;AAC1F,OAAO,cAAc,MAAM,iCAAiC,CAAA;AAE5D,OAAO,YAAY,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAExD,OAAO,EACL,qBAAqB,EAEtB,MAAM,8BAA8B,CAAA;AAOrC;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,UAAU,CAAE,cAAc,CAAE;IACrE;;OAEG;;IAKH;;;;;OAKG;IACH,gBAAuB,QAAQ,gBAAsB;IAErD;;;;;;;OAOG;IACI,gBAAgB,CACnB,KAAK,EAAE,aAAa,EACpB,UAAU,CAAC,EAAE,qBAAqB,GAAI,CAAC,WAAW,EAAE,YAAY,GAAG,SAAS,CAAC;IAMjF;;;;;;;;OAQG;IACU,qBAAqB,CAC9B,KAAK,EAAE,aAAa,EACpB,UAAU,CAAC,EAAE,qBAAqB,GAClC,OAAO,CAAC,CAAC,WAAW,EAAE,YAAY,GAAG,SAAS,CAAC,CAAC;IAMpD;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACI,kBAAkB,CACrB,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,qBAAqB,EAC5B,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAAE,GACzE;QAAC,WAAW;QAAE,YAAY,GAAG,SAAS;KAAC;CAgB5C"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import StepParser from "../step/parsing/step_parser.js";
|
|
2
2
|
import EntitTypesIfcSearch from "./ifc4_gen/entity_types_search.gen.js";
|
|
3
3
|
import IfcStepModel from "./ifc_step_model.js";
|
|
4
|
+
import { buildIndexStreaming } from "../step/parsing/streaming_index_builder.js";
|
|
5
|
+
import { WindowedStepBufferProvider, } from "../step/step_buffer_provider.js";
|
|
6
|
+
/** Default moving-window size for the streaming index build (1 MiB). */
|
|
7
|
+
// eslint-disable-next-line no-magic-numbers
|
|
8
|
+
const DEFAULT_STREAM_POOL_BYTES = 1024 * 1024;
|
|
4
9
|
/**
|
|
5
10
|
* Parser for taking IFC file serialized in step and turning them into a lazily parsed model.
|
|
6
11
|
*/
|
|
@@ -36,6 +41,41 @@ class IfcStepParser extends StepParser {
|
|
|
36
41
|
const [itemIndex, parseResult] = await this.parseDataBlockAsync(input, onProgress);
|
|
37
42
|
return [parseResult, new IfcStepModel(input.buffer, itemIndex.elements)];
|
|
38
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Build a model by streaming the source through a bounded moving window
|
|
46
|
+
* (see buildIndexStreaming / M0) rather than parsing one resident buffer,
|
|
47
|
+
* then backing the model with a windowed provider over `store` — so the
|
|
48
|
+
* source is never held fully resident in the JS heap.
|
|
49
|
+
*
|
|
50
|
+
* `source` serves the parse (synchronous windowed reads — on a worker this
|
|
51
|
+
* is an OPFS sync-access handle; in node/tests a file descriptor or buffer)
|
|
52
|
+
* and `store` serves the model's post-parse property access (asynchronous
|
|
53
|
+
* windowed reads paged in on demand — OPFS `File.slice()` in the browser).
|
|
54
|
+
* Both view the same file bytes, so the file-absolute addresses the index
|
|
55
|
+
* records resolve identically through either.
|
|
56
|
+
*
|
|
57
|
+
* NOTE (M1 scope): this delivers the bounded-memory *parse*. Synchronous
|
|
58
|
+
* geometry extraction still needs its record ranges resident — as after
|
|
59
|
+
* `spillSourceToExternalStore` — so a caller that extracts geometry must
|
|
60
|
+
* `ensureResident` first (demand-driven geometry is M3). Property / index
|
|
61
|
+
* access works directly via the async surfaces.
|
|
62
|
+
*
|
|
63
|
+
* @param source Synchronous byte source feeding the streaming parse.
|
|
64
|
+
* @param store Async external store backing the windowed model.
|
|
65
|
+
* @param opts Optional window sizing: `pool` (parse window),
|
|
66
|
+
* `chunkBytes` / `maxResidentChunks` (model window).
|
|
67
|
+
* @return {[ParseResult, IfcStepModel | undefined]} The parse result and
|
|
68
|
+
* the windowed model.
|
|
69
|
+
*/
|
|
70
|
+
parseStreamToModel(source, store, opts) {
|
|
71
|
+
if (store.byteLength !== source.byteLength) {
|
|
72
|
+
throw new Error(`Streaming store byteLength ${store.byteLength} does not match ` +
|
|
73
|
+
`source byteLength ${source.byteLength}`);
|
|
74
|
+
}
|
|
75
|
+
const { elements, result } = buildIndexStreaming(source, this, opts?.pool ?? DEFAULT_STREAM_POOL_BYTES);
|
|
76
|
+
const provider = new WindowedStepBufferProvider(store, opts?.chunkBytes, opts?.maxResidentChunks);
|
|
77
|
+
return [result, new IfcStepModel(void 0, elements, provider)];
|
|
78
|
+
}
|
|
39
79
|
}
|
|
40
80
|
/**
|
|
41
81
|
* An easily accessible and re-usable instance of the parser.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ifc_stream_model.test.d.ts","sourceRoot":"","sources":["../../../src/ifc/ifc_stream_model.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/* eslint-disable no-magic-numbers */
|
|
2
|
+
// M1 core: a model built by streaming the source through a bounded window
|
|
3
|
+
// (parseStreamToModel) must decode records byte-identically to the resident
|
|
4
|
+
// parse — reading them on demand through the windowed provider after
|
|
5
|
+
// ensureResident, with the source never held fully resident.
|
|
6
|
+
import * as fs from "fs";
|
|
7
|
+
import { beforeAll, describe, expect, test } from "@jest/globals";
|
|
8
|
+
import ParsingBuffer from "../parsing/parsing_buffer.js";
|
|
9
|
+
import IfcStepParser from "./ifc_step_parser.js";
|
|
10
|
+
import { BufferByteSource } from "../step/parsing/byte_source.js";
|
|
11
|
+
import { InMemoryStepByteStore } from "../step/step_buffer_provider.js";
|
|
12
|
+
import { ParseResult } from "../step/parsing/step_parser.js";
|
|
13
|
+
import { IfcRoot } from "./ifc4_gen/index.js";
|
|
14
|
+
let bytes;
|
|
15
|
+
/**
|
|
16
|
+
* Decode every IfcRoot-derived entity's GlobalId + Name from a model into a
|
|
17
|
+
* stable map — the attributes are read from the record bytes, so this
|
|
18
|
+
* exercises the actual byte path (resident buffer vs windowed provider).
|
|
19
|
+
*
|
|
20
|
+
* @param model The model to read from.
|
|
21
|
+
* @return {Map<number, string>} expressID → "GlobalId|Name".
|
|
22
|
+
*/
|
|
23
|
+
function rootAttributes(model) {
|
|
24
|
+
const out = new Map();
|
|
25
|
+
for (const expressID of model.expressIDsOfTypes(IfcRoot)) {
|
|
26
|
+
const entity = model.getElementByExpressID(expressID);
|
|
27
|
+
if (entity === void 0) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const globalId = typeof entity.GlobalId === "string" ? entity.GlobalId : "";
|
|
31
|
+
const name = typeof entity.Name === "string" ? entity.Name : "";
|
|
32
|
+
out.set(expressID, `${globalId}|${name}`);
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
beforeAll(() => {
|
|
37
|
+
bytes = new Uint8Array(fs.readFileSync("data/index.ifc"));
|
|
38
|
+
});
|
|
39
|
+
describe("parseStreamToModel", () => {
|
|
40
|
+
test("streamed windowed model decodes records identically to the resident parse", async () => {
|
|
41
|
+
// Resident ground truth.
|
|
42
|
+
const residentInput = new ParsingBuffer(bytes);
|
|
43
|
+
IfcStepParser.Instance.parseHeader(residentInput);
|
|
44
|
+
const [, residentModel] = IfcStepParser.Instance.parseDataToModel(residentInput);
|
|
45
|
+
const expected = rootAttributes(residentModel);
|
|
46
|
+
expect(expected.size).toBeGreaterThan(10);
|
|
47
|
+
// Streamed: tiny parse window forces slides; tiny model chunks force
|
|
48
|
+
// paging. Same bytes behind both the sync source and the async store.
|
|
49
|
+
const [result, streamModel] = IfcStepParser.Instance.parseStreamToModel(new BufferByteSource(bytes), new InMemoryStepByteStore(bytes), { pool: 4 * 1024, chunkBytes: 512, maxResidentChunks: 3 });
|
|
50
|
+
expect(result).toBe(ParseResult.COMPLETE);
|
|
51
|
+
expect(streamModel.isSourceExternal).toBe(true);
|
|
52
|
+
// Page each record in on demand, then decode; must match resident.
|
|
53
|
+
const actual = new Map();
|
|
54
|
+
for (const expressID of streamModel.expressIDsOfTypes(IfcRoot)) {
|
|
55
|
+
await streamModel.ensureResidentByExpressID(expressID);
|
|
56
|
+
const entity = streamModel.getElementByExpressID(expressID);
|
|
57
|
+
if (entity === void 0) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const globalId = typeof entity.GlobalId === "string" ? entity.GlobalId : "";
|
|
61
|
+
const name = typeof entity.Name === "string" ? entity.Name : "";
|
|
62
|
+
actual.set(expressID, `${globalId}|${name}`);
|
|
63
|
+
}
|
|
64
|
+
expect(actual).toEqual(expected);
|
|
65
|
+
}, 60000);
|
|
66
|
+
test("rejects a store whose size does not match the source", () => {
|
|
67
|
+
expect(() => IfcStepParser.Instance.parseStreamToModel(new BufferByteSource(bytes), new InMemoryStepByteStore(bytes.subarray(0, bytes.length - 1))))
|
|
68
|
+
.toThrow(/does not match/);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -61,6 +61,29 @@ export default class ParsingBuffer {
|
|
|
61
61
|
* of the buffer.
|
|
62
62
|
*/
|
|
63
63
|
reinit(buffer: Uint8Array, initialOffset: number, endOffset: number): void;
|
|
64
|
+
/**
|
|
65
|
+
* Streaming support: repoint this buffer at a fresh window over the same
|
|
66
|
+
* logical stream while keeping `address` file-absolute.
|
|
67
|
+
*
|
|
68
|
+
* A moving-window parse holds only a slice of the source in memory at a
|
|
69
|
+
* time. Between top-level records (where the rewind stack is empty) the
|
|
70
|
+
* driver slides the window forward: it copies the unconsumed tail to the
|
|
71
|
+
* front of a reused buffer, appends freshly-read bytes, and calls this to
|
|
72
|
+
* repoint the parser. `addressBase` is the file offset that window index 0
|
|
73
|
+
* now corresponds to; we store it as a negative initial offset so
|
|
74
|
+
* `address` ( = cursor − initialOffset ) stays the file-absolute value the
|
|
75
|
+
* non-streaming parse would have produced.
|
|
76
|
+
*
|
|
77
|
+
* Must only be called with the rewind stack empty (i.e. at a record
|
|
78
|
+
* boundary) — the stack holds window-relative cursors that a slide would
|
|
79
|
+
* invalidate. Throws otherwise.
|
|
80
|
+
*
|
|
81
|
+
* @param buffer The new window buffer.
|
|
82
|
+
* @param cursorInWindow The cursor position within the new window.
|
|
83
|
+
* @param endInWindow The count of valid bytes in the new window.
|
|
84
|
+
* @param addressBase The file offset that window index 0 maps to.
|
|
85
|
+
*/
|
|
86
|
+
rebaseWindow(buffer: Uint8Array, cursorInWindow: number, endInWindow: number, addressBase: number): void;
|
|
64
87
|
/**
|
|
65
88
|
* Construct this with a buffer, initial offset into the buffer and an end offset.
|
|
66
89
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parsing_buffer.d.ts","sourceRoot":"","sources":["../../../src/parsing/parsing_buffer.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,gBAAgB,CAAA;AAKvC,OAAO,EACL,YAAY,EACZ,uBAAuB,IAAI,qBAAqB,EACjD,MAAM,iBAAiB,CAAA;AAkCxB;;GAEG;AACH,MAAM,WAAW,eAAe;IAE5B,KAAK,CAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAI,MAAM,GAAG,SAAS,CAAC;CACtF;AAED;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,aAAa;
|
|
1
|
+
{"version":3,"file":"parsing_buffer.d.ts","sourceRoot":"","sources":["../../../src/parsing/parsing_buffer.ts"],"names":[],"mappings":"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"}
|
|
@@ -86,6 +86,37 @@ export default class ParsingBuffer {
|
|
|
86
86
|
this.buffer = buffer;
|
|
87
87
|
this.end = endOffset;
|
|
88
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Streaming support: repoint this buffer at a fresh window over the same
|
|
91
|
+
* logical stream while keeping `address` file-absolute.
|
|
92
|
+
*
|
|
93
|
+
* A moving-window parse holds only a slice of the source in memory at a
|
|
94
|
+
* time. Between top-level records (where the rewind stack is empty) the
|
|
95
|
+
* driver slides the window forward: it copies the unconsumed tail to the
|
|
96
|
+
* front of a reused buffer, appends freshly-read bytes, and calls this to
|
|
97
|
+
* repoint the parser. `addressBase` is the file offset that window index 0
|
|
98
|
+
* now corresponds to; we store it as a negative initial offset so
|
|
99
|
+
* `address` ( = cursor − initialOffset ) stays the file-absolute value the
|
|
100
|
+
* non-streaming parse would have produced.
|
|
101
|
+
*
|
|
102
|
+
* Must only be called with the rewind stack empty (i.e. at a record
|
|
103
|
+
* boundary) — the stack holds window-relative cursors that a slide would
|
|
104
|
+
* invalidate. Throws otherwise.
|
|
105
|
+
*
|
|
106
|
+
* @param buffer The new window buffer.
|
|
107
|
+
* @param cursorInWindow The cursor position within the new window.
|
|
108
|
+
* @param endInWindow The count of valid bytes in the new window.
|
|
109
|
+
* @param addressBase The file offset that window index 0 maps to.
|
|
110
|
+
*/
|
|
111
|
+
rebaseWindow(buffer, cursorInWindow, endInWindow, addressBase) {
|
|
112
|
+
if (this.rewindStack_.length !== 0) {
|
|
113
|
+
throw Error("rebaseWindow called mid-transaction (rewind stack non-empty)");
|
|
114
|
+
}
|
|
115
|
+
this.buffer = buffer;
|
|
116
|
+
this.cursor_ = cursorInWindow;
|
|
117
|
+
this.initialOffset_ = -addressBase;
|
|
118
|
+
this.end = endInWindow;
|
|
119
|
+
}
|
|
89
120
|
/**
|
|
90
121
|
* Construct this with a buffer, initial offset into the buffer and an end offset.
|
|
91
122
|
*
|