@bldrs-ai/conway 1.408.1248 → 1.409.1251

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 (37) hide show
  1. package/compiled/examples/browser-bundled.cjs +238 -13
  2. package/compiled/examples/cli-bundled.cjs +238 -13
  3. package/compiled/examples/cli-step-bundled.cjs +104 -9
  4. package/compiled/examples/validator-bundled.cjs +238 -13
  5. package/compiled/src/AP214E3_2010/ap214_step_model.d.ts +2 -1
  6. package/compiled/src/AP214E3_2010/ap214_step_model.d.ts.map +1 -1
  7. package/compiled/src/AP214E3_2010/ap214_step_model.js +1 -1
  8. package/compiled/src/ifc/ifc_step_model.d.ts +2 -1
  9. package/compiled/src/ifc/ifc_step_model.d.ts.map +1 -1
  10. package/compiled/src/ifc/ifc_step_model.js +1 -1
  11. package/compiled/src/ifc/ifc_step_parser.d.ts.map +1 -1
  12. package/compiled/src/ifc/ifc_step_parser.js +5 -3
  13. package/compiled/src/step/indexing/step_type_indexer.d.ts +20 -0
  14. package/compiled/src/step/indexing/step_type_indexer.d.ts.map +1 -1
  15. package/compiled/src/step/indexing/step_type_indexer.js +67 -0
  16. package/compiled/src/step/parsing/columnar_index.d.ts +81 -0
  17. package/compiled/src/step/parsing/columnar_index.d.ts.map +1 -0
  18. package/compiled/src/step/parsing/columnar_index.js +159 -0
  19. package/compiled/src/step/parsing/columnar_index.test.d.ts +2 -0
  20. package/compiled/src/step/parsing/columnar_index.test.d.ts.map +1 -0
  21. package/compiled/src/step/parsing/columnar_index.test.js +155 -0
  22. package/compiled/src/step/parsing/index_sidecar.d.ts +28 -0
  23. package/compiled/src/step/parsing/index_sidecar.d.ts.map +1 -1
  24. package/compiled/src/step/parsing/index_sidecar.js +117 -0
  25. package/compiled/src/step/parsing/index_sidecar.test.js +31 -1
  26. package/compiled/src/step/parsing/step_parser.d.ts +22 -1
  27. package/compiled/src/step/parsing/step_parser.d.ts.map +1 -1
  28. package/compiled/src/step/parsing/step_parser.js +19 -7
  29. package/compiled/src/step/parsing/streaming_index_builder.d.ts +29 -2
  30. package/compiled/src/step/parsing/streaming_index_builder.d.ts.map +1 -1
  31. package/compiled/src/step/parsing/streaming_index_builder.js +23 -2
  32. package/compiled/src/step/step_model_base.d.ts +2 -1
  33. package/compiled/src/step/step_model_base.d.ts.map +1 -1
  34. package/compiled/src/step/step_model_base.js +31 -0
  35. package/compiled/src/version/version.js +1 -1
  36. package/compiled/tsconfig.tsbuildinfo +1 -1
  37. package/package.json +1 -1
@@ -30,7 +30,7 @@ var import_node_process = require("node:process");
30
30
  var readline = __toESM(require("node:readline"), 1);
31
31
 
32
32
  // compiled/src/version/version.js
33
- var versionString = "Conway v1.408.1248";
33
+ var versionString = "Conway v1.409.1251";
34
34
 
35
35
  // compiled/dependencies/conway-geom/interface/conway_geometry.js
36
36
  var wasmType = "";
@@ -2587,8 +2587,8 @@ var StepParser = class extends StepHeaderParser {
2587
2587
  * @param onProgress Optional byte-cursor progress callback.
2588
2588
  * @return {BlockParseResult} The parsing result, including the index and result enum.
2589
2589
  */
2590
- parseDataBlockStreamed(input2, onRecordBoundary, onRecordIndexed, onProgress) {
2591
- const parser211 = this.parseDataBlockIncremental(input2, onRecordBoundary, onRecordIndexed);
2590
+ parseDataBlockStreamed(input2, onRecordBoundary, onRecordIndexed, onProgress, sink) {
2591
+ const parser211 = this.parseDataBlockIncremental(input2, onRecordBoundary, onRecordIndexed, sink);
2592
2592
  while (true) {
2593
2593
  const next = parser211.next();
2594
2594
  if (next.done === true) {
@@ -2634,8 +2634,14 @@ var StepParser = class extends StepHeaderParser {
2634
2634
  * @yields {number} The current byte cursor within the input buffer.
2635
2635
  * @return {BlockParseResult} The parsing result, including the index and result enum.
2636
2636
  */
2637
- *parseDataBlockIncremental(input2, onRecordBoundary, onRecordIndexed) {
2637
+ *parseDataBlockIncremental(input2, onRecordBoundary, onRecordIndexed, sink) {
2638
2638
  const indexResult = { elements: [] };
2639
+ let topLevelCount = 0;
2640
+ const pushEntry = sink !== void 0 ? (entry) => {
2641
+ sink.pushTopLevel(entry);
2642
+ } : (entry) => {
2643
+ indexResult.elements.push(entry);
2644
+ };
2639
2645
  const match = input2.match;
2640
2646
  const comment = () => match(commentParser2);
2641
2647
  const whitespace = () => {
@@ -2811,8 +2817,9 @@ var StepParser = class extends StepHeaderParser {
2811
2817
  if (!charws(SEMICOLON)) {
2812
2818
  return syntaxError();
2813
2819
  }
2814
- onRecordIndexed?.(indexResult.elements.length, expressID, 0);
2815
- indexResult.elements.push({
2820
+ onRecordIndexed?.(topLevelCount, expressID, 0);
2821
+ ++topLevelCount;
2822
+ pushEntry({
2816
2823
  address: startElement2,
2817
2824
  length: input2.address - startElement2,
2818
2825
  typeID: 0,
@@ -2903,8 +2910,9 @@ var StepParser = class extends StepHeaderParser {
2903
2910
  if (!charws(SEMICOLON)) {
2904
2911
  return syntaxError();
2905
2912
  }
2906
- onRecordIndexed?.(indexResult.elements.length, expressID, foundItem);
2907
- indexResult.elements.push({
2913
+ onRecordIndexed?.(topLevelCount, expressID, foundItem);
2914
+ ++topLevelCount;
2915
+ pushEntry({
2908
2916
  address: startElement,
2909
2917
  length: input2.address - startElement,
2910
2918
  typeID: foundItem,
@@ -5000,6 +5008,31 @@ var StepModelBase = class {
5000
5008
  this.elementMemoization = true;
5001
5009
  this.nullOnErrors = true;
5002
5010
  this.bufferProvider_ = provider ?? new ResidentStepBufferProvider(buffer_);
5011
+ if (!Array.isArray(elementIndex)) {
5012
+ const columns = elementIndex;
5013
+ const firstInline = columns.firstInlineElement;
5014
+ const inlineCount = columns.count - firstInline;
5015
+ const inlineElementTable2 = new Uint32Array(inlineCount << 1);
5016
+ for (let where2 = 0; where2 < inlineCount; ++where2) {
5017
+ inlineElementTable2[where2 << 1] = firstInline + where2;
5018
+ inlineElementTable2[(where2 << 1) + 1] = columns.address[firstInline + where2];
5019
+ }
5020
+ this.inlineAddressMap_ = new InterpolationSearchTable32(inlineElementTable2, true);
5021
+ const expressIdTable2 = new Uint32Array(firstInline << 1);
5022
+ for (let where2 = 0; where2 < firstInline; ++where2) {
5023
+ expressIdTable2[where2 << 1] = where2;
5024
+ expressIdTable2[(where2 << 1) + 1] = columns.expressID[where2];
5025
+ }
5026
+ this.expressIDMap_ = new InterpolationSearchTable32(expressIdTable2, columns.expressIdsSorted);
5027
+ this.address_ = columns.address;
5028
+ this.length_ = columns.length;
5029
+ this.typeID_ = columns.typeID;
5030
+ this.expressID_ = columns.expressID;
5031
+ this.count_ = columns.count;
5032
+ this.firstInlineElement_ = firstInline;
5033
+ this.complexEntries_ = columns.complexEntries;
5034
+ return;
5035
+ }
5003
5036
  const localElementIndex = elementIndex;
5004
5037
  let where = 0;
5005
5038
  const firstInlineElement = localElementIndex.length;
@@ -70117,6 +70150,68 @@ var StepTypeIndexer = class {
70117
70150
  constructor(typeCount) {
70118
70151
  this.elementCounter_ = new Int32Array(typeCount << 1);
70119
70152
  }
70153
+ /**
70154
+ * Create a type index from either index form — the parsed object array or
70155
+ * the columnar index (M7).
70156
+ *
70157
+ * @param index The element index, object or columnar.
70158
+ * @return {MultiIndexSet} The created multi-set index.
70159
+ */
70160
+ createFor(index) {
70161
+ return Array.isArray(index) ? this.create(index) : this.createFromColumns(index);
70162
+ }
70163
+ /**
70164
+ * Create a type index straight from the columnar index — the same
70165
+ * membership `create` produces from the unfolded object array: every row's
70166
+ * concrete type (top-level + inline; −1 rows skipped) plus the
70167
+ * multi-mapping subtypes of retained complex entries at their parent's
70168
+ * dense index.
70169
+ *
70170
+ * @param columns The columnar index.
70171
+ * @return {MultiIndexSet} The created multi-set index.
70172
+ */
70173
+ createFromColumns(columns) {
70174
+ for (let where = 0, end = this.elementCounter_.length; where < end; where += 2) {
70175
+ initCountCompactedElements32State(this.elementCounter_, where);
70176
+ }
70177
+ const elementCounter = this.elementCounter_;
70178
+ const prefixSum = new Uint32Array((this.elementCounter_.length >>> 1) + 1);
70179
+ const typeIDs = columns.typeID;
70180
+ const count = columns.count;
70181
+ const walkRows = (addOne) => {
70182
+ const complexIterator = columns.complexEntries?.entries();
70183
+ let nextComplex = complexIterator?.next();
70184
+ for (let denseIndex = 0; denseIndex < count; ++denseIndex) {
70185
+ const typeID = typeIDs[denseIndex];
70186
+ if (typeID >= 0) {
70187
+ addOne(denseIndex, typeID);
70188
+ }
70189
+ if (nextComplex !== void 0 && !nextComplex.done && nextComplex.value[0] === denseIndex) {
70190
+ for (const subElement of nextComplex.value[1].multiMapping ?? []) {
70191
+ const subTypeID = subElement.typeID;
70192
+ if (subTypeID !== void 0) {
70193
+ addOne(denseIndex, subTypeID);
70194
+ }
70195
+ }
70196
+ nextComplex = complexIterator.next();
70197
+ }
70198
+ }
70199
+ };
70200
+ walkRows((denseIndex, typeID) => {
70201
+ prefixSum[typeID + 1] = addCompactedElementCount32State(denseIndex, elementCounter, typeID << 1);
70202
+ });
70203
+ for (let prefixSumIndex = 2, prefixSumEnd = prefixSum.length; prefixSumIndex < prefixSumEnd; ++prefixSumIndex) {
70204
+ prefixSum[prefixSumIndex] += prefixSum[prefixSumIndex - 1];
70205
+ }
70206
+ for (let where = 0, end = this.elementCounter_.length; where < end; where += 2) {
70207
+ initCountCompactedElements32State(this.elementCounter_, where);
70208
+ }
70209
+ const indexOutput = new Uint32Array(prefixSum[prefixSum.length - 1] << 1);
70210
+ walkRows((denseIndex, typeID) => {
70211
+ addCompactedElement32State(denseIndex, elementCounter, indexOutput, typeID << 1, prefixSum[typeID] << 1);
70212
+ });
70213
+ return new MultiIndexSet(prefixSum, indexOutput);
70214
+ }
70120
70215
  /**
70121
70216
  * Create a type index from a set of parsed STEP elements.
70122
70217
  *
@@ -70778,12 +70873,136 @@ var IfcStepModel = class extends StepModelBase {
70778
70873
  this.materials = new IfcMaterialCache(this);
70779
70874
  this.voidMaterials = new IfcMaterialCache(this, true);
70780
70875
  this.elementTypeIDs = entity_types_ifc_gen_default;
70781
- this.typeIndex = indexerInstance.create(elementIndex);
70876
+ this.typeIndex = indexerInstance.createFor(elementIndex);
70877
+ }
70878
+ };
70879
+
70880
+ // compiled/src/step/parsing/columnar_index.js
70881
+ var COLUMN_UNDEFINED_TYPE = -1;
70882
+ var SEGMENT_ROWS = 64 * 1024;
70883
+ var ColumnarIndexSink = class {
70884
+ constructor() {
70885
+ this.segments_ = [];
70886
+ this.count_ = 0;
70887
+ this.retained_ = /* @__PURE__ */ new Map();
70888
+ this.expressIdsSorted_ = true;
70889
+ this.previousExpressID_ = 0;
70890
+ }
70891
+ /**
70892
+ * @return {number} Top-level records pushed so far.
70893
+ */
70894
+ get topLevelCount() {
70895
+ return this.count_;
70896
+ }
70897
+ /**
70898
+ * Encode one completed top-level record into the columns. The entry object
70899
+ * is not kept unless it carries children (inline entities / multi-mapping).
70900
+ *
70901
+ * @param entry The completed top-level index entry.
70902
+ */
70903
+ pushTopLevel(entry) {
70904
+ const localID = this.count_++;
70905
+ const segmentIndex = Math.floor(localID / SEGMENT_ROWS);
70906
+ const row = localID % SEGMENT_ROWS;
70907
+ if (segmentIndex === this.segments_.length) {
70908
+ this.segments_.push({
70909
+ address: new Uint32Array(SEGMENT_ROWS),
70910
+ length: new Uint32Array(SEGMENT_ROWS),
70911
+ typeID: new Int32Array(SEGMENT_ROWS),
70912
+ expressID: new Uint32Array(SEGMENT_ROWS)
70913
+ });
70914
+ }
70915
+ const segment = this.segments_[segmentIndex];
70916
+ segment.address[row] = entry.address;
70917
+ segment.length[row] = entry.length;
70918
+ segment.typeID[row] = entry.typeID === void 0 ? COLUMN_UNDEFINED_TYPE : entry.typeID;
70919
+ segment.expressID[row] = entry.expressID;
70920
+ if (entry.expressID < this.previousExpressID_) {
70921
+ this.expressIdsSorted_ = false;
70922
+ }
70923
+ this.previousExpressID_ = entry.expressID;
70924
+ if (entry.inlineEntities !== void 0 || entry.multiMapping !== void 0) {
70925
+ this.retained_.set(localID, entry);
70926
+ }
70927
+ }
70928
+ /**
70929
+ * Rewind to empty (the streaming builder's grow-and-restart). The first
70930
+ * segment is kept for reuse.
70931
+ */
70932
+ reset() {
70933
+ this.segments_.length = Math.min(this.segments_.length, 1);
70934
+ this.count_ = 0;
70935
+ this.retained_.clear();
70936
+ this.expressIdsSorted_ = true;
70937
+ this.previousExpressID_ = 0;
70938
+ }
70939
+ /**
70940
+ * Assemble the final columns: concatenate the top-level segments (one
70941
+ * column at a time, bounding transient overhead to a single column's
70942
+ * segments) and unfold retained inline entities into the inline range in
70943
+ * the model's exact unfold order.
70944
+ *
70945
+ * @return {StepIndexColumns} The finished columnar index.
70946
+ */
70947
+ finalize() {
70948
+ const topLevel = this.count_;
70949
+ const unfolded = [];
70950
+ for (const entry of this.retained_.values()) {
70951
+ if (entry.inlineEntities !== void 0) {
70952
+ unfolded.push(...entry.inlineEntities);
70953
+ }
70954
+ }
70955
+ for (let where = 0; where < unfolded.length; ++where) {
70956
+ const inlineEntities = unfolded[where].inlineEntities;
70957
+ if (inlineEntities !== void 0) {
70958
+ unfolded.push(...inlineEntities);
70959
+ }
70960
+ }
70961
+ const count = topLevel + unfolded.length;
70962
+ const address = concatColumn(this.segments_, "address", topLevel, count);
70963
+ const length = concatColumn(this.segments_, "length", topLevel, count);
70964
+ const typeID = new Int32Array(count);
70965
+ for (let segment = 0; segment * SEGMENT_ROWS < topLevel; ++segment) {
70966
+ const rows = Math.min(SEGMENT_ROWS, topLevel - segment * SEGMENT_ROWS);
70967
+ typeID.set(this.segments_[segment].typeID.subarray(0, rows), segment * SEGMENT_ROWS);
70968
+ }
70969
+ const expressID = concatColumn(this.segments_, "expressID", topLevel, topLevel);
70970
+ for (let where = 0; where < unfolded.length; ++where) {
70971
+ const entry = unfolded[where];
70972
+ const row = topLevel + where;
70973
+ address[row] = entry.address;
70974
+ length[row] = entry.length;
70975
+ typeID[row] = entry.typeID === void 0 ? COLUMN_UNDEFINED_TYPE : entry.typeID;
70976
+ }
70977
+ let complexEntries;
70978
+ for (const [localID, entry] of this.retained_) {
70979
+ if (entry.multiMapping !== void 0) {
70980
+ (complexEntries ??= /* @__PURE__ */ new Map()).set(localID, entry);
70981
+ }
70982
+ }
70983
+ return {
70984
+ address,
70985
+ length,
70986
+ typeID,
70987
+ expressID,
70988
+ count,
70989
+ firstInlineElement: topLevel,
70990
+ complexEntries,
70991
+ expressIdsSorted: this.expressIdsSorted_
70992
+ };
70782
70993
  }
70783
70994
  };
70995
+ function concatColumn(segments, column, rows, finalLength) {
70996
+ const result = new Uint32Array(finalLength);
70997
+ for (let segment = 0; segment * SEGMENT_ROWS < rows; ++segment) {
70998
+ const valid = Math.min(SEGMENT_ROWS, rows - segment * SEGMENT_ROWS);
70999
+ result.set(segments[segment][column].subarray(0, valid), segment * SEGMENT_ROWS);
71000
+ }
71001
+ return result;
71002
+ }
70784
71003
 
70785
71004
  // compiled/src/step/parsing/streaming_index_builder.js
70786
- function buildIndexStreaming(source, parser211, pool3, onRecordIndexed) {
71005
+ function buildIndexStreaming(source, parser211, pool3, onRecordIndexed, sink) {
70787
71006
  const fileSize = source.byteLength;
70788
71007
  let windowBytes = Math.max(pool3, MIN_WINDOW);
70789
71008
  for (; ; ) {
@@ -70829,11 +71048,12 @@ function buildIndexStreaming(source, parser211, pool3, onRecordIndexed) {
70829
71048
  buffer.rebaseWindow(window2, 0, windowLen, windowStartFile);
70830
71049
  ++slides;
70831
71050
  };
70832
- const [index, result] = parser211.parseDataBlockStreamed(input2, onRecordBoundary, onRecordIndexed);
71051
+ const [index, result] = parser211.parseDataBlockStreamed(input2, onRecordBoundary, onRecordIndexed, void 0, sink);
70833
71052
  const stoppedShort = result !== ParseResult.COMPLETE;
70834
71053
  const notAtEof = windowStartFile + windowLen < fileSize;
70835
71054
  if (stoppedShort && notAtEof) {
70836
71055
  windowBytes *= 2;
71056
+ sink?.reset();
70837
71057
  continue;
70838
71058
  }
70839
71059
  const lastRecordLen = windowStartFile + input2.cursor - prevBoundaryFile;
@@ -70849,6 +71069,11 @@ function buildIndexStreaming(source, parser211, pool3, onRecordIndexed) {
70849
71069
  }
70850
71070
  }
70851
71071
  var MIN_WINDOW = 4 * 1024;
71072
+ function buildColumnarIndexStreaming(source, parser211, pool3, onRecordIndexed) {
71073
+ const sink = new ColumnarIndexSink();
71074
+ const { header, result, stats } = buildIndexStreaming(source, parser211, pool3, onRecordIndexed, sink);
71075
+ return { header, columns: sink.finalize(), result, stats };
71076
+ }
70852
71077
 
70853
71078
  // compiled/src/ifc/ifc_step_parser.js
70854
71079
  var DEFAULT_STREAM_POOL_BYTES = 1024 * 1024;
@@ -70914,9 +71139,9 @@ var IfcStepParser = class extends StepParser {
70914
71139
  if (store.byteLength !== source.byteLength) {
70915
71140
  throw new Error(`Streaming store byteLength ${store.byteLength} does not match source byteLength ${source.byteLength}`);
70916
71141
  }
70917
- const { elements, result } = buildIndexStreaming(source, this, opts?.pool ?? DEFAULT_STREAM_POOL_BYTES);
71142
+ const { columns, result } = buildColumnarIndexStreaming(source, this, opts?.pool ?? DEFAULT_STREAM_POOL_BYTES);
70918
71143
  const provider = new WindowedStepBufferProvider(store, opts?.chunkBytes, opts?.maxResidentChunks);
70919
- return [result, new IfcStepModel(void 0, elements, provider)];
71144
+ return [result, new IfcStepModel(void 0, columns, provider)];
70920
71145
  }
70921
71146
  };
70922
71147
  IfcStepParser.Instance = new IfcStepParser();
@@ -14965,7 +14965,7 @@ ${t5.join("\n")}` : "";
14965
14965
  var import_process = require("process");
14966
14966
 
14967
14967
  // compiled/src/version/version.js
14968
- var versionString = "Conway v1.408.1248";
14968
+ var versionString = "Conway v1.409.1251";
14969
14969
 
14970
14970
  // compiled/dependencies/conway-geom/interface/conway_geometry.js
14971
14971
  function pThreadsAllowed() {
@@ -18401,8 +18401,8 @@ var StepParser = class extends StepHeaderParser {
18401
18401
  * @param onProgress Optional byte-cursor progress callback.
18402
18402
  * @return {BlockParseResult} The parsing result, including the index and result enum.
18403
18403
  */
18404
- parseDataBlockStreamed(input, onRecordBoundary, onRecordIndexed, onProgress) {
18405
- const parser210 = this.parseDataBlockIncremental(input, onRecordBoundary, onRecordIndexed);
18404
+ parseDataBlockStreamed(input, onRecordBoundary, onRecordIndexed, onProgress, sink) {
18405
+ const parser210 = this.parseDataBlockIncremental(input, onRecordBoundary, onRecordIndexed, sink);
18406
18406
  while (true) {
18407
18407
  const next = parser210.next();
18408
18408
  if (next.done === true) {
@@ -18448,8 +18448,14 @@ var StepParser = class extends StepHeaderParser {
18448
18448
  * @yields {number} The current byte cursor within the input buffer.
18449
18449
  * @return {BlockParseResult} The parsing result, including the index and result enum.
18450
18450
  */
18451
- *parseDataBlockIncremental(input, onRecordBoundary, onRecordIndexed) {
18451
+ *parseDataBlockIncremental(input, onRecordBoundary, onRecordIndexed, sink) {
18452
18452
  const indexResult = { elements: [] };
18453
+ let topLevelCount = 0;
18454
+ const pushEntry = sink !== void 0 ? (entry) => {
18455
+ sink.pushTopLevel(entry);
18456
+ } : (entry) => {
18457
+ indexResult.elements.push(entry);
18458
+ };
18453
18459
  const match = input.match;
18454
18460
  const comment = () => match(commentParser2);
18455
18461
  const whitespace = () => {
@@ -18625,8 +18631,9 @@ var StepParser = class extends StepHeaderParser {
18625
18631
  if (!charws(SEMICOLON)) {
18626
18632
  return syntaxError();
18627
18633
  }
18628
- onRecordIndexed?.(indexResult.elements.length, expressID, 0);
18629
- indexResult.elements.push({
18634
+ onRecordIndexed?.(topLevelCount, expressID, 0);
18635
+ ++topLevelCount;
18636
+ pushEntry({
18630
18637
  address: startElement2,
18631
18638
  length: input.address - startElement2,
18632
18639
  typeID: 0,
@@ -18717,8 +18724,9 @@ var StepParser = class extends StepHeaderParser {
18717
18724
  if (!charws(SEMICOLON)) {
18718
18725
  return syntaxError();
18719
18726
  }
18720
- onRecordIndexed?.(indexResult.elements.length, expressID, foundItem);
18721
- indexResult.elements.push({
18727
+ onRecordIndexed?.(topLevelCount, expressID, foundItem);
18728
+ ++topLevelCount;
18729
+ pushEntry({
18722
18730
  address: startElement,
18723
18731
  length: input.address - startElement,
18724
18732
  typeID: foundItem,
@@ -20814,6 +20822,31 @@ var StepModelBase = class {
20814
20822
  this.elementMemoization = true;
20815
20823
  this.nullOnErrors = true;
20816
20824
  this.bufferProvider_ = provider ?? new ResidentStepBufferProvider(buffer_);
20825
+ if (!Array.isArray(elementIndex)) {
20826
+ const columns = elementIndex;
20827
+ const firstInline = columns.firstInlineElement;
20828
+ const inlineCount = columns.count - firstInline;
20829
+ const inlineElementTable2 = new Uint32Array(inlineCount << 1);
20830
+ for (let where2 = 0; where2 < inlineCount; ++where2) {
20831
+ inlineElementTable2[where2 << 1] = firstInline + where2;
20832
+ inlineElementTable2[(where2 << 1) + 1] = columns.address[firstInline + where2];
20833
+ }
20834
+ this.inlineAddressMap_ = new InterpolationSearchTable32(inlineElementTable2, true);
20835
+ const expressIdTable2 = new Uint32Array(firstInline << 1);
20836
+ for (let where2 = 0; where2 < firstInline; ++where2) {
20837
+ expressIdTable2[where2 << 1] = where2;
20838
+ expressIdTable2[(where2 << 1) + 1] = columns.expressID[where2];
20839
+ }
20840
+ this.expressIDMap_ = new InterpolationSearchTable32(expressIdTable2, columns.expressIdsSorted);
20841
+ this.address_ = columns.address;
20842
+ this.length_ = columns.length;
20843
+ this.typeID_ = columns.typeID;
20844
+ this.expressID_ = columns.expressID;
20845
+ this.count_ = columns.count;
20846
+ this.firstInlineElement_ = firstInline;
20847
+ this.complexEntries_ = columns.complexEntries;
20848
+ return;
20849
+ }
20817
20850
  const localElementIndex = elementIndex;
20818
20851
  let where = 0;
20819
20852
  const firstInlineElement = localElementIndex.length;
@@ -85931,6 +85964,68 @@ var StepTypeIndexer = class {
85931
85964
  constructor(typeCount) {
85932
85965
  this.elementCounter_ = new Int32Array(typeCount << 1);
85933
85966
  }
85967
+ /**
85968
+ * Create a type index from either index form — the parsed object array or
85969
+ * the columnar index (M7).
85970
+ *
85971
+ * @param index The element index, object or columnar.
85972
+ * @return {MultiIndexSet} The created multi-set index.
85973
+ */
85974
+ createFor(index) {
85975
+ return Array.isArray(index) ? this.create(index) : this.createFromColumns(index);
85976
+ }
85977
+ /**
85978
+ * Create a type index straight from the columnar index — the same
85979
+ * membership `create` produces from the unfolded object array: every row's
85980
+ * concrete type (top-level + inline; −1 rows skipped) plus the
85981
+ * multi-mapping subtypes of retained complex entries at their parent's
85982
+ * dense index.
85983
+ *
85984
+ * @param columns The columnar index.
85985
+ * @return {MultiIndexSet} The created multi-set index.
85986
+ */
85987
+ createFromColumns(columns) {
85988
+ for (let where = 0, end = this.elementCounter_.length; where < end; where += 2) {
85989
+ initCountCompactedElements32State(this.elementCounter_, where);
85990
+ }
85991
+ const elementCounter = this.elementCounter_;
85992
+ const prefixSum = new Uint32Array((this.elementCounter_.length >>> 1) + 1);
85993
+ const typeIDs = columns.typeID;
85994
+ const count = columns.count;
85995
+ const walkRows = (addOne) => {
85996
+ const complexIterator = columns.complexEntries?.entries();
85997
+ let nextComplex = complexIterator?.next();
85998
+ for (let denseIndex = 0; denseIndex < count; ++denseIndex) {
85999
+ const typeID = typeIDs[denseIndex];
86000
+ if (typeID >= 0) {
86001
+ addOne(denseIndex, typeID);
86002
+ }
86003
+ if (nextComplex !== void 0 && !nextComplex.done && nextComplex.value[0] === denseIndex) {
86004
+ for (const subElement of nextComplex.value[1].multiMapping ?? []) {
86005
+ const subTypeID = subElement.typeID;
86006
+ if (subTypeID !== void 0) {
86007
+ addOne(denseIndex, subTypeID);
86008
+ }
86009
+ }
86010
+ nextComplex = complexIterator.next();
86011
+ }
86012
+ }
86013
+ };
86014
+ walkRows((denseIndex, typeID) => {
86015
+ prefixSum[typeID + 1] = addCompactedElementCount32State(denseIndex, elementCounter, typeID << 1);
86016
+ });
86017
+ for (let prefixSumIndex = 2, prefixSumEnd = prefixSum.length; prefixSumIndex < prefixSumEnd; ++prefixSumIndex) {
86018
+ prefixSum[prefixSumIndex] += prefixSum[prefixSumIndex - 1];
86019
+ }
86020
+ for (let where = 0, end = this.elementCounter_.length; where < end; where += 2) {
86021
+ initCountCompactedElements32State(this.elementCounter_, where);
86022
+ }
86023
+ const indexOutput = new Uint32Array(prefixSum[prefixSum.length - 1] << 1);
86024
+ walkRows((denseIndex, typeID) => {
86025
+ addCompactedElement32State(denseIndex, elementCounter, indexOutput, typeID << 1, prefixSum[typeID] << 1);
86026
+ });
86027
+ return new MultiIndexSet(prefixSum, indexOutput);
86028
+ }
85934
86029
  /**
85935
86030
  * Create a type index from a set of parsed STEP elements.
85936
86031
  *
@@ -86623,12 +86718,136 @@ var IfcStepModel = class extends StepModelBase {
86623
86718
  this.materials = new IfcMaterialCache(this);
86624
86719
  this.voidMaterials = new IfcMaterialCache(this, true);
86625
86720
  this.elementTypeIDs = entity_types_ifc_gen_default;
86626
- this.typeIndex = indexerInstance.create(elementIndex);
86721
+ this.typeIndex = indexerInstance.createFor(elementIndex);
86722
+ }
86723
+ };
86724
+
86725
+ // compiled/src/step/parsing/columnar_index.js
86726
+ var COLUMN_UNDEFINED_TYPE = -1;
86727
+ var SEGMENT_ROWS = 64 * 1024;
86728
+ var ColumnarIndexSink = class {
86729
+ constructor() {
86730
+ this.segments_ = [];
86731
+ this.count_ = 0;
86732
+ this.retained_ = /* @__PURE__ */ new Map();
86733
+ this.expressIdsSorted_ = true;
86734
+ this.previousExpressID_ = 0;
86735
+ }
86736
+ /**
86737
+ * @return {number} Top-level records pushed so far.
86738
+ */
86739
+ get topLevelCount() {
86740
+ return this.count_;
86741
+ }
86742
+ /**
86743
+ * Encode one completed top-level record into the columns. The entry object
86744
+ * is not kept unless it carries children (inline entities / multi-mapping).
86745
+ *
86746
+ * @param entry The completed top-level index entry.
86747
+ */
86748
+ pushTopLevel(entry) {
86749
+ const localID = this.count_++;
86750
+ const segmentIndex = Math.floor(localID / SEGMENT_ROWS);
86751
+ const row = localID % SEGMENT_ROWS;
86752
+ if (segmentIndex === this.segments_.length) {
86753
+ this.segments_.push({
86754
+ address: new Uint32Array(SEGMENT_ROWS),
86755
+ length: new Uint32Array(SEGMENT_ROWS),
86756
+ typeID: new Int32Array(SEGMENT_ROWS),
86757
+ expressID: new Uint32Array(SEGMENT_ROWS)
86758
+ });
86759
+ }
86760
+ const segment = this.segments_[segmentIndex];
86761
+ segment.address[row] = entry.address;
86762
+ segment.length[row] = entry.length;
86763
+ segment.typeID[row] = entry.typeID === void 0 ? COLUMN_UNDEFINED_TYPE : entry.typeID;
86764
+ segment.expressID[row] = entry.expressID;
86765
+ if (entry.expressID < this.previousExpressID_) {
86766
+ this.expressIdsSorted_ = false;
86767
+ }
86768
+ this.previousExpressID_ = entry.expressID;
86769
+ if (entry.inlineEntities !== void 0 || entry.multiMapping !== void 0) {
86770
+ this.retained_.set(localID, entry);
86771
+ }
86772
+ }
86773
+ /**
86774
+ * Rewind to empty (the streaming builder's grow-and-restart). The first
86775
+ * segment is kept for reuse.
86776
+ */
86777
+ reset() {
86778
+ this.segments_.length = Math.min(this.segments_.length, 1);
86779
+ this.count_ = 0;
86780
+ this.retained_.clear();
86781
+ this.expressIdsSorted_ = true;
86782
+ this.previousExpressID_ = 0;
86783
+ }
86784
+ /**
86785
+ * Assemble the final columns: concatenate the top-level segments (one
86786
+ * column at a time, bounding transient overhead to a single column's
86787
+ * segments) and unfold retained inline entities into the inline range in
86788
+ * the model's exact unfold order.
86789
+ *
86790
+ * @return {StepIndexColumns} The finished columnar index.
86791
+ */
86792
+ finalize() {
86793
+ const topLevel = this.count_;
86794
+ const unfolded = [];
86795
+ for (const entry of this.retained_.values()) {
86796
+ if (entry.inlineEntities !== void 0) {
86797
+ unfolded.push(...entry.inlineEntities);
86798
+ }
86799
+ }
86800
+ for (let where = 0; where < unfolded.length; ++where) {
86801
+ const inlineEntities = unfolded[where].inlineEntities;
86802
+ if (inlineEntities !== void 0) {
86803
+ unfolded.push(...inlineEntities);
86804
+ }
86805
+ }
86806
+ const count = topLevel + unfolded.length;
86807
+ const address = concatColumn(this.segments_, "address", topLevel, count);
86808
+ const length = concatColumn(this.segments_, "length", topLevel, count);
86809
+ const typeID = new Int32Array(count);
86810
+ for (let segment = 0; segment * SEGMENT_ROWS < topLevel; ++segment) {
86811
+ const rows = Math.min(SEGMENT_ROWS, topLevel - segment * SEGMENT_ROWS);
86812
+ typeID.set(this.segments_[segment].typeID.subarray(0, rows), segment * SEGMENT_ROWS);
86813
+ }
86814
+ const expressID = concatColumn(this.segments_, "expressID", topLevel, topLevel);
86815
+ for (let where = 0; where < unfolded.length; ++where) {
86816
+ const entry = unfolded[where];
86817
+ const row = topLevel + where;
86818
+ address[row] = entry.address;
86819
+ length[row] = entry.length;
86820
+ typeID[row] = entry.typeID === void 0 ? COLUMN_UNDEFINED_TYPE : entry.typeID;
86821
+ }
86822
+ let complexEntries;
86823
+ for (const [localID, entry] of this.retained_) {
86824
+ if (entry.multiMapping !== void 0) {
86825
+ (complexEntries ??= /* @__PURE__ */ new Map()).set(localID, entry);
86826
+ }
86827
+ }
86828
+ return {
86829
+ address,
86830
+ length,
86831
+ typeID,
86832
+ expressID,
86833
+ count,
86834
+ firstInlineElement: topLevel,
86835
+ complexEntries,
86836
+ expressIdsSorted: this.expressIdsSorted_
86837
+ };
86627
86838
  }
86628
86839
  };
86840
+ function concatColumn(segments, column, rows, finalLength) {
86841
+ const result = new Uint32Array(finalLength);
86842
+ for (let segment = 0; segment * SEGMENT_ROWS < rows; ++segment) {
86843
+ const valid = Math.min(SEGMENT_ROWS, rows - segment * SEGMENT_ROWS);
86844
+ result.set(segments[segment][column].subarray(0, valid), segment * SEGMENT_ROWS);
86845
+ }
86846
+ return result;
86847
+ }
86629
86848
 
86630
86849
  // compiled/src/step/parsing/streaming_index_builder.js
86631
- function buildIndexStreaming(source, parser210, pool3, onRecordIndexed) {
86850
+ function buildIndexStreaming(source, parser210, pool3, onRecordIndexed, sink) {
86632
86851
  const fileSize = source.byteLength;
86633
86852
  let windowBytes = Math.max(pool3, MIN_WINDOW);
86634
86853
  for (; ; ) {
@@ -86674,11 +86893,12 @@ function buildIndexStreaming(source, parser210, pool3, onRecordIndexed) {
86674
86893
  buffer.rebaseWindow(window2, 0, windowLen, windowStartFile);
86675
86894
  ++slides;
86676
86895
  };
86677
- const [index, result] = parser210.parseDataBlockStreamed(input, onRecordBoundary, onRecordIndexed);
86896
+ const [index, result] = parser210.parseDataBlockStreamed(input, onRecordBoundary, onRecordIndexed, void 0, sink);
86678
86897
  const stoppedShort = result !== ParseResult.COMPLETE;
86679
86898
  const notAtEof = windowStartFile + windowLen < fileSize;
86680
86899
  if (stoppedShort && notAtEof) {
86681
86900
  windowBytes *= 2;
86901
+ sink?.reset();
86682
86902
  continue;
86683
86903
  }
86684
86904
  const lastRecordLen = windowStartFile + input.cursor - prevBoundaryFile;
@@ -86694,6 +86914,11 @@ function buildIndexStreaming(source, parser210, pool3, onRecordIndexed) {
86694
86914
  }
86695
86915
  }
86696
86916
  var MIN_WINDOW = 4 * 1024;
86917
+ function buildColumnarIndexStreaming(source, parser210, pool3, onRecordIndexed) {
86918
+ const sink = new ColumnarIndexSink();
86919
+ const { header, result, stats } = buildIndexStreaming(source, parser210, pool3, onRecordIndexed, sink);
86920
+ return { header, columns: sink.finalize(), result, stats };
86921
+ }
86697
86922
 
86698
86923
  // compiled/src/ifc/ifc_step_parser.js
86699
86924
  var DEFAULT_STREAM_POOL_BYTES = 1024 * 1024;
@@ -86759,9 +86984,9 @@ var IfcStepParser = class extends StepParser {
86759
86984
  if (store.byteLength !== source.byteLength) {
86760
86985
  throw new Error(`Streaming store byteLength ${store.byteLength} does not match source byteLength ${source.byteLength}`);
86761
86986
  }
86762
- const { elements, result } = buildIndexStreaming(source, this, opts?.pool ?? DEFAULT_STREAM_POOL_BYTES);
86987
+ const { columns, result } = buildColumnarIndexStreaming(source, this, opts?.pool ?? DEFAULT_STREAM_POOL_BYTES);
86763
86988
  const provider = new WindowedStepBufferProvider(store, opts?.chunkBytes, opts?.maxResidentChunks);
86764
- return [result, new IfcStepModel(void 0, elements, provider)];
86989
+ return [result, new IfcStepModel(void 0, columns, provider)];
86765
86990
  }
86766
86991
  };
86767
86992
  IfcStepParser.Instance = new IfcStepParser();