@bldrs-ai/conway 1.408.1248 → 1.413.1255

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 (59) 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 +238 -13
  12. package/compiled/examples/cli-bundled.cjs +265 -40
  13. package/compiled/examples/cli-step-bundled.cjs +131 -36
  14. package/compiled/examples/validator-bundled.cjs +238 -13
  15. package/compiled/src/AP214E3_2010/ap214_step_model.d.ts +2 -1
  16. package/compiled/src/AP214E3_2010/ap214_step_model.d.ts.map +1 -1
  17. package/compiled/src/AP214E3_2010/ap214_step_model.js +1 -1
  18. package/compiled/src/core/demand_residency_pump.d.ts +93 -0
  19. package/compiled/src/core/demand_residency_pump.d.ts.map +1 -0
  20. package/compiled/src/core/demand_residency_pump.js +120 -0
  21. package/compiled/src/core/demand_residency_pump.test.d.ts +2 -0
  22. package/compiled/src/core/demand_residency_pump.test.d.ts.map +1 -0
  23. package/compiled/src/core/demand_residency_pump.test.js +148 -0
  24. package/compiled/src/core/geometry_tile_bindings.d.ts +110 -0
  25. package/compiled/src/core/geometry_tile_bindings.d.ts.map +1 -0
  26. package/compiled/src/core/geometry_tile_bindings.js +76 -0
  27. package/compiled/src/core/geometry_tile_bindings.test.d.ts +2 -0
  28. package/compiled/src/core/geometry_tile_bindings.test.d.ts.map +1 -0
  29. package/compiled/src/core/geometry_tile_bindings.test.js +211 -0
  30. package/compiled/src/ifc/ifc_step_model.d.ts +2 -1
  31. package/compiled/src/ifc/ifc_step_model.d.ts.map +1 -1
  32. package/compiled/src/ifc/ifc_step_model.js +1 -1
  33. package/compiled/src/ifc/ifc_step_parser.d.ts.map +1 -1
  34. package/compiled/src/ifc/ifc_step_parser.js +5 -3
  35. package/compiled/src/step/indexing/step_type_indexer.d.ts +20 -0
  36. package/compiled/src/step/indexing/step_type_indexer.d.ts.map +1 -1
  37. package/compiled/src/step/indexing/step_type_indexer.js +67 -0
  38. package/compiled/src/step/parsing/columnar_index.d.ts +81 -0
  39. package/compiled/src/step/parsing/columnar_index.d.ts.map +1 -0
  40. package/compiled/src/step/parsing/columnar_index.js +159 -0
  41. package/compiled/src/step/parsing/columnar_index.test.d.ts +2 -0
  42. package/compiled/src/step/parsing/columnar_index.test.d.ts.map +1 -0
  43. package/compiled/src/step/parsing/columnar_index.test.js +155 -0
  44. package/compiled/src/step/parsing/index_sidecar.d.ts +28 -0
  45. package/compiled/src/step/parsing/index_sidecar.d.ts.map +1 -1
  46. package/compiled/src/step/parsing/index_sidecar.js +117 -0
  47. package/compiled/src/step/parsing/index_sidecar.test.js +31 -1
  48. package/compiled/src/step/parsing/step_parser.d.ts +22 -1
  49. package/compiled/src/step/parsing/step_parser.d.ts.map +1 -1
  50. package/compiled/src/step/parsing/step_parser.js +19 -7
  51. package/compiled/src/step/parsing/streaming_index_builder.d.ts +29 -2
  52. package/compiled/src/step/parsing/streaming_index_builder.d.ts.map +1 -1
  53. package/compiled/src/step/parsing/streaming_index_builder.js +23 -2
  54. package/compiled/src/step/step_model_base.d.ts +2 -1
  55. package/compiled/src/step/step_model_base.d.ts.map +1 -1
  56. package/compiled/src/step/step_model_base.js +31 -0
  57. package/compiled/src/version/version.js +1 -1
  58. package/compiled/tsconfig.tsbuildinfo +1 -1
  59. 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.408.1248";
947
+ var versionString = "Conway v1.413.1255";
948
948
 
949
949
  // compiled/dependencies/conway-geom/interface/conway_geometry.js
950
950
  var wasmType = "";
@@ -3501,8 +3501,8 @@ var StepParser = class extends StepHeaderParser {
3501
3501
  * @param onProgress Optional byte-cursor progress callback.
3502
3502
  * @return {BlockParseResult} The parsing result, including the index and result enum.
3503
3503
  */
3504
- parseDataBlockStreamed(input, onRecordBoundary, onRecordIndexed, onProgress) {
3505
- const parser211 = this.parseDataBlockIncremental(input, onRecordBoundary, onRecordIndexed);
3504
+ parseDataBlockStreamed(input, onRecordBoundary, onRecordIndexed, onProgress, sink) {
3505
+ const parser211 = this.parseDataBlockIncremental(input, onRecordBoundary, onRecordIndexed, sink);
3506
3506
  while (true) {
3507
3507
  const next = parser211.next();
3508
3508
  if (next.done === true) {
@@ -3548,8 +3548,14 @@ var StepParser = class extends StepHeaderParser {
3548
3548
  * @yields {number} The current byte cursor within the input buffer.
3549
3549
  * @return {BlockParseResult} The parsing result, including the index and result enum.
3550
3550
  */
3551
- *parseDataBlockIncremental(input, onRecordBoundary, onRecordIndexed) {
3551
+ *parseDataBlockIncremental(input, onRecordBoundary, onRecordIndexed, sink) {
3552
3552
  const indexResult = { elements: [] };
3553
+ let topLevelCount = 0;
3554
+ const pushEntry = sink !== void 0 ? (entry) => {
3555
+ sink.pushTopLevel(entry);
3556
+ } : (entry) => {
3557
+ indexResult.elements.push(entry);
3558
+ };
3553
3559
  const match = input.match;
3554
3560
  const comment = () => match(commentParser2);
3555
3561
  const whitespace = () => {
@@ -3725,8 +3731,9 @@ var StepParser = class extends StepHeaderParser {
3725
3731
  if (!charws(SEMICOLON)) {
3726
3732
  return syntaxError();
3727
3733
  }
3728
- onRecordIndexed?.(indexResult.elements.length, expressID, 0);
3729
- indexResult.elements.push({
3734
+ onRecordIndexed?.(topLevelCount, expressID, 0);
3735
+ ++topLevelCount;
3736
+ pushEntry({
3730
3737
  address: startElement2,
3731
3738
  length: input.address - startElement2,
3732
3739
  typeID: 0,
@@ -3817,8 +3824,9 @@ var StepParser = class extends StepHeaderParser {
3817
3824
  if (!charws(SEMICOLON)) {
3818
3825
  return syntaxError();
3819
3826
  }
3820
- onRecordIndexed?.(indexResult.elements.length, expressID, foundItem);
3821
- indexResult.elements.push({
3827
+ onRecordIndexed?.(topLevelCount, expressID, foundItem);
3828
+ ++topLevelCount;
3829
+ pushEntry({
3822
3830
  address: startElement,
3823
3831
  length: input.address - startElement,
3824
3832
  typeID: foundItem,
@@ -4998,6 +5006,31 @@ var StepModelBase = class {
4998
5006
  this.elementMemoization = true;
4999
5007
  this.nullOnErrors = true;
5000
5008
  this.bufferProvider_ = provider ?? new ResidentStepBufferProvider(buffer_);
5009
+ if (!Array.isArray(elementIndex)) {
5010
+ const columns = elementIndex;
5011
+ const firstInline = columns.firstInlineElement;
5012
+ const inlineCount = columns.count - firstInline;
5013
+ const inlineElementTable2 = new Uint32Array(inlineCount << 1);
5014
+ for (let where2 = 0; where2 < inlineCount; ++where2) {
5015
+ inlineElementTable2[where2 << 1] = firstInline + where2;
5016
+ inlineElementTable2[(where2 << 1) + 1] = columns.address[firstInline + where2];
5017
+ }
5018
+ this.inlineAddressMap_ = new InterpolationSearchTable32(inlineElementTable2, true);
5019
+ const expressIdTable2 = new Uint32Array(firstInline << 1);
5020
+ for (let where2 = 0; where2 < firstInline; ++where2) {
5021
+ expressIdTable2[where2 << 1] = where2;
5022
+ expressIdTable2[(where2 << 1) + 1] = columns.expressID[where2];
5023
+ }
5024
+ this.expressIDMap_ = new InterpolationSearchTable32(expressIdTable2, columns.expressIdsSorted);
5025
+ this.address_ = columns.address;
5026
+ this.length_ = columns.length;
5027
+ this.typeID_ = columns.typeID;
5028
+ this.expressID_ = columns.expressID;
5029
+ this.count_ = columns.count;
5030
+ this.firstInlineElement_ = firstInline;
5031
+ this.complexEntries_ = columns.complexEntries;
5032
+ return;
5033
+ }
5001
5034
  const localElementIndex = elementIndex;
5002
5035
  let where = 0;
5003
5036
  const firstInlineElement = localElementIndex.length;
@@ -70115,6 +70148,68 @@ var StepTypeIndexer = class {
70115
70148
  constructor(typeCount) {
70116
70149
  this.elementCounter_ = new Int32Array(typeCount << 1);
70117
70150
  }
70151
+ /**
70152
+ * Create a type index from either index form — the parsed object array or
70153
+ * the columnar index (M7).
70154
+ *
70155
+ * @param index The element index, object or columnar.
70156
+ * @return {MultiIndexSet} The created multi-set index.
70157
+ */
70158
+ createFor(index) {
70159
+ return Array.isArray(index) ? this.create(index) : this.createFromColumns(index);
70160
+ }
70161
+ /**
70162
+ * Create a type index straight from the columnar index — the same
70163
+ * membership `create` produces from the unfolded object array: every row's
70164
+ * concrete type (top-level + inline; −1 rows skipped) plus the
70165
+ * multi-mapping subtypes of retained complex entries at their parent's
70166
+ * dense index.
70167
+ *
70168
+ * @param columns The columnar index.
70169
+ * @return {MultiIndexSet} The created multi-set index.
70170
+ */
70171
+ createFromColumns(columns) {
70172
+ for (let where = 0, end = this.elementCounter_.length; where < end; where += 2) {
70173
+ initCountCompactedElements32State(this.elementCounter_, where);
70174
+ }
70175
+ const elementCounter = this.elementCounter_;
70176
+ const prefixSum = new Uint32Array((this.elementCounter_.length >>> 1) + 1);
70177
+ const typeIDs = columns.typeID;
70178
+ const count = columns.count;
70179
+ const walkRows = (addOne) => {
70180
+ const complexIterator = columns.complexEntries?.entries();
70181
+ let nextComplex = complexIterator?.next();
70182
+ for (let denseIndex = 0; denseIndex < count; ++denseIndex) {
70183
+ const typeID = typeIDs[denseIndex];
70184
+ if (typeID >= 0) {
70185
+ addOne(denseIndex, typeID);
70186
+ }
70187
+ if (nextComplex !== void 0 && !nextComplex.done && nextComplex.value[0] === denseIndex) {
70188
+ for (const subElement of nextComplex.value[1].multiMapping ?? []) {
70189
+ const subTypeID = subElement.typeID;
70190
+ if (subTypeID !== void 0) {
70191
+ addOne(denseIndex, subTypeID);
70192
+ }
70193
+ }
70194
+ nextComplex = complexIterator.next();
70195
+ }
70196
+ }
70197
+ };
70198
+ walkRows((denseIndex, typeID) => {
70199
+ prefixSum[typeID + 1] = addCompactedElementCount32State(denseIndex, elementCounter, typeID << 1);
70200
+ });
70201
+ for (let prefixSumIndex = 2, prefixSumEnd = prefixSum.length; prefixSumIndex < prefixSumEnd; ++prefixSumIndex) {
70202
+ prefixSum[prefixSumIndex] += prefixSum[prefixSumIndex - 1];
70203
+ }
70204
+ for (let where = 0, end = this.elementCounter_.length; where < end; where += 2) {
70205
+ initCountCompactedElements32State(this.elementCounter_, where);
70206
+ }
70207
+ const indexOutput = new Uint32Array(prefixSum[prefixSum.length - 1] << 1);
70208
+ walkRows((denseIndex, typeID) => {
70209
+ addCompactedElement32State(denseIndex, elementCounter, indexOutput, typeID << 1, prefixSum[typeID] << 1);
70210
+ });
70211
+ return new MultiIndexSet(prefixSum, indexOutput);
70212
+ }
70118
70213
  /**
70119
70214
  * Create a type index from a set of parsed STEP elements.
70120
70215
  *
@@ -70776,12 +70871,136 @@ var IfcStepModel = class extends StepModelBase {
70776
70871
  this.materials = new IfcMaterialCache(this);
70777
70872
  this.voidMaterials = new IfcMaterialCache(this, true);
70778
70873
  this.elementTypeIDs = entity_types_ifc_gen_default;
70779
- this.typeIndex = indexerInstance.create(elementIndex);
70874
+ this.typeIndex = indexerInstance.createFor(elementIndex);
70780
70875
  }
70781
70876
  };
70782
70877
 
70878
+ // compiled/src/step/parsing/columnar_index.js
70879
+ var COLUMN_UNDEFINED_TYPE = -1;
70880
+ var SEGMENT_ROWS = 64 * 1024;
70881
+ var ColumnarIndexSink = class {
70882
+ constructor() {
70883
+ this.segments_ = [];
70884
+ this.count_ = 0;
70885
+ this.retained_ = /* @__PURE__ */ new Map();
70886
+ this.expressIdsSorted_ = true;
70887
+ this.previousExpressID_ = 0;
70888
+ }
70889
+ /**
70890
+ * @return {number} Top-level records pushed so far.
70891
+ */
70892
+ get topLevelCount() {
70893
+ return this.count_;
70894
+ }
70895
+ /**
70896
+ * Encode one completed top-level record into the columns. The entry object
70897
+ * is not kept unless it carries children (inline entities / multi-mapping).
70898
+ *
70899
+ * @param entry The completed top-level index entry.
70900
+ */
70901
+ pushTopLevel(entry) {
70902
+ const localID = this.count_++;
70903
+ const segmentIndex = Math.floor(localID / SEGMENT_ROWS);
70904
+ const row = localID % SEGMENT_ROWS;
70905
+ if (segmentIndex === this.segments_.length) {
70906
+ this.segments_.push({
70907
+ address: new Uint32Array(SEGMENT_ROWS),
70908
+ length: new Uint32Array(SEGMENT_ROWS),
70909
+ typeID: new Int32Array(SEGMENT_ROWS),
70910
+ expressID: new Uint32Array(SEGMENT_ROWS)
70911
+ });
70912
+ }
70913
+ const segment = this.segments_[segmentIndex];
70914
+ segment.address[row] = entry.address;
70915
+ segment.length[row] = entry.length;
70916
+ segment.typeID[row] = entry.typeID === void 0 ? COLUMN_UNDEFINED_TYPE : entry.typeID;
70917
+ segment.expressID[row] = entry.expressID;
70918
+ if (entry.expressID < this.previousExpressID_) {
70919
+ this.expressIdsSorted_ = false;
70920
+ }
70921
+ this.previousExpressID_ = entry.expressID;
70922
+ if (entry.inlineEntities !== void 0 || entry.multiMapping !== void 0) {
70923
+ this.retained_.set(localID, entry);
70924
+ }
70925
+ }
70926
+ /**
70927
+ * Rewind to empty (the streaming builder's grow-and-restart). The first
70928
+ * segment is kept for reuse.
70929
+ */
70930
+ reset() {
70931
+ this.segments_.length = Math.min(this.segments_.length, 1);
70932
+ this.count_ = 0;
70933
+ this.retained_.clear();
70934
+ this.expressIdsSorted_ = true;
70935
+ this.previousExpressID_ = 0;
70936
+ }
70937
+ /**
70938
+ * Assemble the final columns: concatenate the top-level segments (one
70939
+ * column at a time, bounding transient overhead to a single column's
70940
+ * segments) and unfold retained inline entities into the inline range in
70941
+ * the model's exact unfold order.
70942
+ *
70943
+ * @return {StepIndexColumns} The finished columnar index.
70944
+ */
70945
+ finalize() {
70946
+ const topLevel = this.count_;
70947
+ const unfolded = [];
70948
+ for (const entry of this.retained_.values()) {
70949
+ if (entry.inlineEntities !== void 0) {
70950
+ unfolded.push(...entry.inlineEntities);
70951
+ }
70952
+ }
70953
+ for (let where = 0; where < unfolded.length; ++where) {
70954
+ const inlineEntities = unfolded[where].inlineEntities;
70955
+ if (inlineEntities !== void 0) {
70956
+ unfolded.push(...inlineEntities);
70957
+ }
70958
+ }
70959
+ const count = topLevel + unfolded.length;
70960
+ const address = concatColumn(this.segments_, "address", topLevel, count);
70961
+ const length = concatColumn(this.segments_, "length", topLevel, count);
70962
+ const typeID = new Int32Array(count);
70963
+ for (let segment = 0; segment * SEGMENT_ROWS < topLevel; ++segment) {
70964
+ const rows = Math.min(SEGMENT_ROWS, topLevel - segment * SEGMENT_ROWS);
70965
+ typeID.set(this.segments_[segment].typeID.subarray(0, rows), segment * SEGMENT_ROWS);
70966
+ }
70967
+ const expressID = concatColumn(this.segments_, "expressID", topLevel, topLevel);
70968
+ for (let where = 0; where < unfolded.length; ++where) {
70969
+ const entry = unfolded[where];
70970
+ const row = topLevel + where;
70971
+ address[row] = entry.address;
70972
+ length[row] = entry.length;
70973
+ typeID[row] = entry.typeID === void 0 ? COLUMN_UNDEFINED_TYPE : entry.typeID;
70974
+ }
70975
+ let complexEntries;
70976
+ for (const [localID, entry] of this.retained_) {
70977
+ if (entry.multiMapping !== void 0) {
70978
+ (complexEntries ??= /* @__PURE__ */ new Map()).set(localID, entry);
70979
+ }
70980
+ }
70981
+ return {
70982
+ address,
70983
+ length,
70984
+ typeID,
70985
+ expressID,
70986
+ count,
70987
+ firstInlineElement: topLevel,
70988
+ complexEntries,
70989
+ expressIdsSorted: this.expressIdsSorted_
70990
+ };
70991
+ }
70992
+ };
70993
+ function concatColumn(segments, column, rows, finalLength) {
70994
+ const result = new Uint32Array(finalLength);
70995
+ for (let segment = 0; segment * SEGMENT_ROWS < rows; ++segment) {
70996
+ const valid = Math.min(SEGMENT_ROWS, rows - segment * SEGMENT_ROWS);
70997
+ result.set(segments[segment][column].subarray(0, valid), segment * SEGMENT_ROWS);
70998
+ }
70999
+ return result;
71000
+ }
71001
+
70783
71002
  // compiled/src/step/parsing/streaming_index_builder.js
70784
- function buildIndexStreaming(source, parser211, pool3, onRecordIndexed) {
71003
+ function buildIndexStreaming(source, parser211, pool3, onRecordIndexed, sink) {
70785
71004
  const fileSize = source.byteLength;
70786
71005
  let windowBytes = Math.max(pool3, MIN_WINDOW);
70787
71006
  for (; ; ) {
@@ -70827,11 +71046,12 @@ function buildIndexStreaming(source, parser211, pool3, onRecordIndexed) {
70827
71046
  buffer.rebaseWindow(window2, 0, windowLen, windowStartFile);
70828
71047
  ++slides;
70829
71048
  };
70830
- const [index, result] = parser211.parseDataBlockStreamed(input, onRecordBoundary, onRecordIndexed);
71049
+ const [index, result] = parser211.parseDataBlockStreamed(input, onRecordBoundary, onRecordIndexed, void 0, sink);
70831
71050
  const stoppedShort = result !== ParseResult.COMPLETE;
70832
71051
  const notAtEof = windowStartFile + windowLen < fileSize;
70833
71052
  if (stoppedShort && notAtEof) {
70834
71053
  windowBytes *= 2;
71054
+ sink?.reset();
70835
71055
  continue;
70836
71056
  }
70837
71057
  const lastRecordLen = windowStartFile + input.cursor - prevBoundaryFile;
@@ -70847,6 +71067,11 @@ function buildIndexStreaming(source, parser211, pool3, onRecordIndexed) {
70847
71067
  }
70848
71068
  }
70849
71069
  var MIN_WINDOW = 4 * 1024;
71070
+ function buildColumnarIndexStreaming(source, parser211, pool3, onRecordIndexed) {
71071
+ const sink = new ColumnarIndexSink();
71072
+ const { header, result, stats } = buildIndexStreaming(source, parser211, pool3, onRecordIndexed, sink);
71073
+ return { header, columns: sink.finalize(), result, stats };
71074
+ }
70850
71075
 
70851
71076
  // compiled/src/ifc/ifc_step_parser.js
70852
71077
  var DEFAULT_STREAM_POOL_BYTES = 1024 * 1024;
@@ -70912,9 +71137,9 @@ var IfcStepParser = class extends StepParser {
70912
71137
  if (store.byteLength !== source.byteLength) {
70913
71138
  throw new Error(`Streaming store byteLength ${store.byteLength} does not match source byteLength ${source.byteLength}`);
70914
71139
  }
70915
- const { elements, result } = buildIndexStreaming(source, this, opts?.pool ?? DEFAULT_STREAM_POOL_BYTES);
71140
+ const { columns, result } = buildColumnarIndexStreaming(source, this, opts?.pool ?? DEFAULT_STREAM_POOL_BYTES);
70916
71141
  const provider = new WindowedStepBufferProvider(store, opts?.chunkBytes, opts?.maxResidentChunks);
70917
- return [result, new IfcStepModel(void 0, elements, provider)];
71142
+ return [result, new IfcStepModel(void 0, columns, provider)];
70918
71143
  }
70919
71144
  };
70920
71145
  IfcStepParser.Instance = new IfcStepParser();
@@ -1,6 +1,7 @@
1
1
  import EntityTypesAP214 from "./AP214E3_2010_gen/entity_types_ap214.gen.js";
2
2
  import StepModelBase from "../step/step_model_base.js";
3
3
  import { StepIndexEntry } from "../step/parsing/step_parser.js";
4
+ import { StepIndexColumns } from "../step/parsing/columnar_index.js";
4
5
  import { MultiIndexSet } from "../indexing/multi_index_set.js";
5
6
  import { AP214ModelGeometry } from "./ap214_model_geometry.js";
6
7
  import { AP214ModelProfile } from "./ap214_model_profile.js";
@@ -26,6 +27,6 @@ export default class AP214StepModel extends StepModelBase<EntityTypesAP214> {
26
27
  * @param buffer The buffer to values from.
27
28
  * @param elementIndex The parsed index to elements in the STEP.
28
29
  */
29
- constructor(buffer: Uint8Array, elementIndex: StepIndexEntry<EntityTypesAP214>[]);
30
+ constructor(buffer: Uint8Array, elementIndex: StepIndexEntry<EntityTypesAP214>[] | StepIndexColumns<EntityTypesAP214>);
30
31
  }
31
32
  //# sourceMappingURL=ap214_step_model.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ap214_step_model.d.ts","sourceRoot":"","sources":["../../../src/AP214E3_2010/ap214_step_model.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAyC,MAAM,2CAA2C,CAAA;AACjG,OAAO,aAAa,MAAM,yBAAyB,CAAA;AAEnD,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAA;AAE1D,OAAO,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAA;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,wBAAwB,MAAM,+BAA+B,CAAA;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,gBAAgB,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAKvD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,aAAa,CAAE,gBAAgB,CAAE;IAE3E,SAAgB,SAAS,EAAE,aAAa,CAAE,gBAAgB,CAAE,CAAA;IAC5D,SAAgB,mBAAmB,kCAA2B;IAC9D,SAAgB,QAAQ,qBAA2B;IACnD,SAAgB,SAAS,qBAA2B;IACpD,SAAgB,QAAQ,oBAA0B;IAClD,SAAgB,MAAM,mBAA6B;IACnD,SAAgB,aAAa,iBAAuB;IAEpD;;;;;;OAMG;gBAEC,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,cAAc,CAAE,gBAAgB,CAAE,EAAE;CAKvD"}
1
+ {"version":3,"file":"ap214_step_model.d.ts","sourceRoot":"","sources":["../../../src/AP214E3_2010/ap214_step_model.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAyC,MAAM,2CAA2C,CAAA;AACjG,OAAO,aAAa,MAAM,yBAAyB,CAAA;AAEnD,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAA;AAC1D,OAAO,EAAC,gBAAgB,EAAC,MAAM,gCAAgC,CAAA;AAE/D,OAAO,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAA;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,wBAAwB,MAAM,+BAA+B,CAAA;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,gBAAgB,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAKvD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,aAAa,CAAE,gBAAgB,CAAE;IAE3E,SAAgB,SAAS,EAAE,aAAa,CAAE,gBAAgB,CAAE,CAAA;IAC5D,SAAgB,mBAAmB,kCAA2B;IAC9D,SAAgB,QAAQ,qBAA2B;IACnD,SAAgB,SAAS,qBAA2B;IACpD,SAAgB,QAAQ,oBAA0B;IAClD,SAAgB,MAAM,mBAA6B;IACnD,SAAgB,aAAa,iBAAuB;IAEpD;;;;;;OAMG;gBAEC,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,cAAc,CAAE,gBAAgB,CAAE,EAAE,GAAG,gBAAgB,CAAE,gBAAgB,CAAE;CAK9F"}
@@ -28,6 +28,6 @@ export default class AP214StepModel extends StepModelBase {
28
28
  this.profiles = new AP214ModelProfile();
29
29
  this.curves = new AP214ModelCurves(this);
30
30
  this.csgOperations = new CsgMemoization();
31
- this.typeIndex = indexerInstance.create(elementIndex);
31
+ this.typeIndex = indexerInstance.createFor(elementIndex);
32
32
  }
33
33
  }
@@ -0,0 +1,93 @@
1
+ import { DemandGeometryQueue } from "./demand_geometry_queue.js";
2
+ /**
3
+ * The async half of demand-driven geometry (Phase B): source-byte residency.
4
+ *
5
+ * Extraction is synchronous by design (the wasm extract reads source bytes
6
+ * through `StepBufferProvider.acquire`), but a windowed/streamed source pages
7
+ * bytes in asynchronously (`ensureResident`). This pump owns that seam: it
8
+ * admits demand, prefetches the source ranges for the most-wanted products,
9
+ * and only then forwards them to the synchronous {@link DemandGeometryQueue}
10
+ * — so a `pump()` never hits a non-resident range mid-extract.
11
+ */
12
+ export interface ResidencyPrefetcher {
13
+ /**
14
+ * Page in the source byte ranges a product's extraction will read.
15
+ * `StepModelBase.ensureResidentByLocalID` satisfies this shape.
16
+ *
17
+ * @param localID The product's local ID.
18
+ * @return {Promise<void>} Resolves when resident.
19
+ */
20
+ ensureResidentByLocalID(localID: number): Promise<void>;
21
+ }
22
+ /** Outcome of one pump cycle, for telemetry and tests. */
23
+ export interface PumpResult {
24
+ /** Tiles extracted this cycle (from the queue's pump). */
25
+ extracted: number;
26
+ /** Products whose prefetch failed this cycle (re-queued for retry). */
27
+ prefetchFailures: number;
28
+ }
29
+ /**
30
+ * Admission + prefetch orchestration in front of a {@link DemandGeometryQueue}.
31
+ *
32
+ * Consumers `request()` products as demand changes (the pump owns admission —
33
+ * don't request on the queue directly); each async `pump()` cycle:
34
+ *
35
+ * 1. selects the top-priority pending batch,
36
+ * 2. awaits source residency for the batch (failures re-queue for retry
37
+ * and are reported, never thrown — one bad range must not stall the
38
+ * viewport),
39
+ * 3. forwards the resident products to the queue and runs its synchronous
40
+ * pump under the same batch cap.
41
+ *
42
+ * Re-entrant calls coalesce: a `pump()` while one is in flight returns the
43
+ * in-flight cycle's promise rather than interleaving prefetch batches.
44
+ * Products already resident in the queue skip prefetch entirely (their
45
+ * ranking refresh is forwarded immediately).
46
+ */
47
+ export declare class DemandResidencyPump {
48
+ private readonly queue_;
49
+ private readonly prefetcher_;
50
+ private readonly batch_;
51
+ /** Pending admission: product localID → highest requested priority. */
52
+ private readonly pending_;
53
+ private inFlight_;
54
+ /**
55
+ * @param queue_ The synchronous demand queue (extraction + budget).
56
+ * @param prefetcher_ Source-byte residency (the model / buffer provider).
57
+ * @param batch_ Max products prefetched + extracted per pump cycle.
58
+ */
59
+ constructor(queue_: DemandGeometryQueue, prefetcher_: ResidencyPrefetcher, batch_?: number);
60
+ /**
61
+ * Request a product at a demand priority. Resident products forward
62
+ * immediately (ranking refresh); others queue for the next pump cycle at
63
+ * the highest priority requested so far.
64
+ *
65
+ * @param productLocalID The product to materialise.
66
+ * @param priority The demand priority (higher = more wanted).
67
+ */
68
+ request(productLocalID: number, priority: number): void;
69
+ /**
70
+ * @return {number} Products awaiting admission (not yet prefetched).
71
+ */
72
+ get pendingCount(): number;
73
+ /**
74
+ * Run one admission cycle (see class docs). Coalesces with an in-flight
75
+ * cycle.
76
+ *
77
+ * @return {Promise<PumpResult>} The cycle's outcome.
78
+ */
79
+ pump(): Promise<PumpResult>;
80
+ /**
81
+ * One cycle: select top batch → prefetch → forward + queue pump.
82
+ *
83
+ * @return {Promise<PumpResult>} The cycle's outcome.
84
+ */
85
+ private pumpCycle_;
86
+ /**
87
+ * Remove and return the top-priority pending entries, up to the batch cap.
88
+ *
89
+ * @return {[number, number][]} `[productLocalID, priority]` pairs.
90
+ */
91
+ private takeTopPending_;
92
+ }
93
+ //# sourceMappingURL=demand_residency_pump.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demand_residency_pump.d.ts","sourceRoot":"","sources":["../../../src/core/demand_residency_pump.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAG7D;;;;;;;;;GASG;AACH,MAAM,WAAW,mBAAmB;IAElC;;;;;;OAMG;IACH,uBAAuB,CAAE,OAAO,EAAE,MAAM,GAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1D;AAGD,0DAA0D;AAC1D,MAAM,WAAW,UAAU;IAEzB,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAA;IAEjB,uEAAuE;IACvE,gBAAgB,EAAE,MAAM,CAAA;CACzB;AASD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,mBAAmB;IAa5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAbzB,uEAAuE;IACvE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4B;IAErD,OAAO,CAAC,SAAS,CAAiC;IAElD;;;;OAIG;gBAEgB,MAAM,EAAE,mBAAmB,EAC3B,WAAW,EAAE,mBAAmB,EAChC,MAAM,GAAE,MAAsB;IAOjD;;;;;;;OAOG;IACI,OAAO,CAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAI,IAAI;IAchE;;OAEG;IACH,IAAW,YAAY,IAAI,MAAM,CAEhC;IAED;;;;;OAKG;IACI,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;IAalC;;;;OAIG;YACW,UAAU;IAkCxB;;;;OAIG;IACH,OAAO,CAAC,eAAe;CAkBxB"}
@@ -0,0 +1,120 @@
1
+ // Defaults chosen for frame-cooperative pumping: enough per cycle to fill
2
+ // quickly, small enough that a cycle stays well under a frame budget once
3
+ // extraction costs are real. Both are tunable per call site.
4
+ const DEFAULT_BATCH = 32;
5
+ /**
6
+ * Admission + prefetch orchestration in front of a {@link DemandGeometryQueue}.
7
+ *
8
+ * Consumers `request()` products as demand changes (the pump owns admission —
9
+ * don't request on the queue directly); each async `pump()` cycle:
10
+ *
11
+ * 1. selects the top-priority pending batch,
12
+ * 2. awaits source residency for the batch (failures re-queue for retry
13
+ * and are reported, never thrown — one bad range must not stall the
14
+ * viewport),
15
+ * 3. forwards the resident products to the queue and runs its synchronous
16
+ * pump under the same batch cap.
17
+ *
18
+ * Re-entrant calls coalesce: a `pump()` while one is in flight returns the
19
+ * in-flight cycle's promise rather than interleaving prefetch batches.
20
+ * Products already resident in the queue skip prefetch entirely (their
21
+ * ranking refresh is forwarded immediately).
22
+ */
23
+ export class DemandResidencyPump {
24
+ /**
25
+ * @param queue_ The synchronous demand queue (extraction + budget).
26
+ * @param prefetcher_ Source-byte residency (the model / buffer provider).
27
+ * @param batch_ Max products prefetched + extracted per pump cycle.
28
+ */
29
+ constructor(queue_, prefetcher_, batch_ = DEFAULT_BATCH) {
30
+ this.queue_ = queue_;
31
+ this.prefetcher_ = prefetcher_;
32
+ this.batch_ = batch_;
33
+ /** Pending admission: product localID → highest requested priority. */
34
+ this.pending_ = new Map();
35
+ if (batch_ < 1) {
36
+ throw new Error(`Invalid batch ${batch_}`);
37
+ }
38
+ }
39
+ /**
40
+ * Request a product at a demand priority. Resident products forward
41
+ * immediately (ranking refresh); others queue for the next pump cycle at
42
+ * the highest priority requested so far.
43
+ *
44
+ * @param productLocalID The product to materialise.
45
+ * @param priority The demand priority (higher = more wanted).
46
+ */
47
+ request(productLocalID, priority) {
48
+ if (this.queue_.isResident(productLocalID)) {
49
+ this.queue_.request(productLocalID, priority);
50
+ return;
51
+ }
52
+ const existing = this.pending_.get(productLocalID);
53
+ this.pending_.set(productLocalID, existing === void 0 ? priority : Math.max(existing, priority));
54
+ }
55
+ /**
56
+ * @return {number} Products awaiting admission (not yet prefetched).
57
+ */
58
+ get pendingCount() {
59
+ return this.pending_.size;
60
+ }
61
+ /**
62
+ * Run one admission cycle (see class docs). Coalesces with an in-flight
63
+ * cycle.
64
+ *
65
+ * @return {Promise<PumpResult>} The cycle's outcome.
66
+ */
67
+ pump() {
68
+ if (this.inFlight_ !== void 0) {
69
+ return this.inFlight_;
70
+ }
71
+ this.inFlight_ = this.pumpCycle_().finally(() => {
72
+ this.inFlight_ = void 0;
73
+ });
74
+ return this.inFlight_;
75
+ }
76
+ /**
77
+ * One cycle: select top batch → prefetch → forward + queue pump.
78
+ *
79
+ * @return {Promise<PumpResult>} The cycle's outcome.
80
+ */
81
+ async pumpCycle_() {
82
+ const batch = this.takeTopPending_();
83
+ if (batch.length === 0) {
84
+ // Nothing to admit; still give the queue a chance to fill from its own
85
+ // pending set (e.g. entries deferred by an earlier budget refusal).
86
+ return { extracted: this.queue_.pump(this.batch_), prefetchFailures: 0 };
87
+ }
88
+ const outcomes = await Promise.allSettled(batch.map(([productLocalID]) => this.prefetcher_.ensureResidentByLocalID(productLocalID)));
89
+ let prefetchFailures = 0;
90
+ for (let where = 0; where < batch.length; ++where) {
91
+ const [productLocalID, priority] = batch[where];
92
+ if (outcomes[where].status === 'fulfilled') {
93
+ this.queue_.request(productLocalID, priority);
94
+ continue;
95
+ }
96
+ // Failed prefetch: re-queue for a later cycle (transient store errors
97
+ // retry; persistent ones keep surfacing in the failure count).
98
+ ++prefetchFailures;
99
+ this.request(productLocalID, priority);
100
+ }
101
+ return { extracted: this.queue_.pump(this.batch_), prefetchFailures };
102
+ }
103
+ /**
104
+ * Remove and return the top-priority pending entries, up to the batch cap.
105
+ *
106
+ * @return {[number, number][]} `[productLocalID, priority]` pairs.
107
+ */
108
+ takeTopPending_() {
109
+ if (this.pending_.size === 0) {
110
+ return [];
111
+ }
112
+ const entries = [...this.pending_.entries()];
113
+ entries.sort((a, b) => b[1] - a[1]);
114
+ const batch = entries.slice(0, this.batch_);
115
+ for (const [productLocalID] of batch) {
116
+ this.pending_.delete(productLocalID);
117
+ }
118
+ return batch;
119
+ }
120
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=demand_residency_pump.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demand_residency_pump.test.d.ts","sourceRoot":"","sources":["../../../src/core/demand_residency_pump.test.ts"],"names":[],"mappings":""}