@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.
Files changed (56) hide show
  1. package/compiled/Dist/ConwayGeomWasmNode.js +0 -0
  2. package/compiled/Dist/ConwayGeomWasmNodeMT.js +0 -0
  3. package/compiled/Dist/ConwayGeomWasmWeb.js +0 -0
  4. package/compiled/Dist/ConwayGeomWasmWebMT.js +1 -1
  5. package/compiled/Dist/ConwayGeomWasmWebMT.wasm +0 -0
  6. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNode.js +0 -0
  7. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNodeMT.js +0 -0
  8. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWeb.js +0 -0
  9. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWebMT.js +1 -1
  10. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWebMT.wasm +0 -0
  11. package/compiled/examples/browser-bundled.cjs +184 -11
  12. package/compiled/examples/cli-bundled.cjs +213 -40
  13. package/compiled/examples/cli-step-bundled.cjs +105 -37
  14. package/compiled/examples/validator-bundled.cjs +184 -11
  15. package/compiled/src/ifc/ifc_step_model.d.ts +5 -2
  16. package/compiled/src/ifc/ifc_step_model.d.ts.map +1 -1
  17. package/compiled/src/ifc/ifc_step_model.js +5 -3
  18. package/compiled/src/ifc/ifc_step_parser.d.ts +36 -0
  19. package/compiled/src/ifc/ifc_step_parser.d.ts.map +1 -1
  20. package/compiled/src/ifc/ifc_step_parser.js +40 -0
  21. package/compiled/src/ifc/ifc_stream_model.test.d.ts +2 -0
  22. package/compiled/src/ifc/ifc_stream_model.test.d.ts.map +1 -0
  23. package/compiled/src/ifc/ifc_stream_model.test.js +70 -0
  24. package/compiled/src/parsing/parsing_buffer.d.ts +23 -0
  25. package/compiled/src/parsing/parsing_buffer.d.ts.map +1 -1
  26. package/compiled/src/parsing/parsing_buffer.js +31 -0
  27. package/compiled/src/step/parsing/byte_source.d.ts +55 -0
  28. package/compiled/src/step/parsing/byte_source.d.ts.map +1 -0
  29. package/compiled/src/step/parsing/byte_source.js +35 -0
  30. package/compiled/src/step/parsing/incremental_type_index.d.ts +64 -0
  31. package/compiled/src/step/parsing/incremental_type_index.d.ts.map +1 -0
  32. package/compiled/src/step/parsing/incremental_type_index.js +92 -0
  33. package/compiled/src/step/parsing/incremental_type_index.test.d.ts +2 -0
  34. package/compiled/src/step/parsing/incremental_type_index.test.d.ts.map +1 -0
  35. package/compiled/src/step/parsing/incremental_type_index.test.js +55 -0
  36. package/compiled/src/step/parsing/step_parser.d.ts +19 -0
  37. package/compiled/src/step/parsing/step_parser.d.ts.map +1 -1
  38. package/compiled/src/step/parsing/step_parser.js +48 -4
  39. package/compiled/src/step/parsing/streaming_index_builder.d.ts +70 -0
  40. package/compiled/src/step/parsing/streaming_index_builder.d.ts.map +1 -0
  41. package/compiled/src/step/parsing/streaming_index_builder.js +125 -0
  42. package/compiled/src/step/parsing/streaming_index_builder.test.d.ts +2 -0
  43. package/compiled/src/step/parsing/streaming_index_builder.test.d.ts.map +1 -0
  44. package/compiled/src/step/parsing/streaming_index_builder.test.js +107 -0
  45. package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts +55 -0
  46. package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts.map +1 -0
  47. package/compiled/src/step/parsing/streaming_record_dispatcher.js +67 -0
  48. package/compiled/src/step/parsing/streaming_record_dispatcher.test.d.ts +2 -0
  49. package/compiled/src/step/parsing/streaming_record_dispatcher.test.d.ts.map +1 -0
  50. package/compiled/src/step/parsing/streaming_record_dispatcher.test.js +66 -0
  51. package/compiled/src/step/step_model_base.d.ts +9 -3
  52. package/compiled/src/step/step_model_base.d.ts.map +1 -1
  53. package/compiled/src/step/step_model_base.js +9 -3
  54. package/compiled/src/version/version.js +1 -1
  55. package/compiled/tsconfig.tsbuildinfo +1 -1
  56. 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.399.1223";
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.cursor;
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.cursor;
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.cursor;
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;AAKvD;;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;;;;;;OAMG;gBAEC,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,cAAc,CAAE,cAAc,CAAE,EAAE;CAKrD"}
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;AAE3C;;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;CAKrD"}
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ifc_stream_model.test.d.ts.map
@@ -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":"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"}
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
  *