@bldrs-ai/conway 1.399.1223 → 1.401.1237
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiled/Dist/ConwayGeomWasmNode.js +0 -0
- package/compiled/Dist/ConwayGeomWasmNodeMT.js +0 -0
- package/compiled/Dist/ConwayGeomWasmWeb.js +0 -0
- package/compiled/Dist/ConwayGeomWasmWebMT.js +1 -1
- package/compiled/Dist/ConwayGeomWasmWebMT.wasm +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNode.js +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNodeMT.js +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWeb.js +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWebMT.js +1 -1
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWebMT.wasm +0 -0
- package/compiled/examples/browser-bundled.cjs +184 -11
- package/compiled/examples/cli-bundled.cjs +213 -40
- package/compiled/examples/cli-step-bundled.cjs +105 -37
- package/compiled/examples/validator-bundled.cjs +184 -11
- package/compiled/src/ifc/ifc_step_model.d.ts +5 -2
- package/compiled/src/ifc/ifc_step_model.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_step_model.js +5 -3
- package/compiled/src/ifc/ifc_step_parser.d.ts +36 -0
- package/compiled/src/ifc/ifc_step_parser.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_step_parser.js +40 -0
- package/compiled/src/ifc/ifc_stream_model.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_stream_model.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_stream_model.test.js +70 -0
- package/compiled/src/parsing/parsing_buffer.d.ts +23 -0
- package/compiled/src/parsing/parsing_buffer.d.ts.map +1 -1
- package/compiled/src/parsing/parsing_buffer.js +31 -0
- package/compiled/src/step/parsing/byte_source.d.ts +55 -0
- package/compiled/src/step/parsing/byte_source.d.ts.map +1 -0
- package/compiled/src/step/parsing/byte_source.js +35 -0
- package/compiled/src/step/parsing/incremental_type_index.d.ts +64 -0
- package/compiled/src/step/parsing/incremental_type_index.d.ts.map +1 -0
- package/compiled/src/step/parsing/incremental_type_index.js +92 -0
- package/compiled/src/step/parsing/incremental_type_index.test.d.ts +2 -0
- package/compiled/src/step/parsing/incremental_type_index.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/incremental_type_index.test.js +55 -0
- package/compiled/src/step/parsing/step_parser.d.ts +19 -0
- package/compiled/src/step/parsing/step_parser.d.ts.map +1 -1
- package/compiled/src/step/parsing/step_parser.js +48 -4
- package/compiled/src/step/parsing/streaming_index_builder.d.ts +70 -0
- package/compiled/src/step/parsing/streaming_index_builder.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_index_builder.js +125 -0
- package/compiled/src/step/parsing/streaming_index_builder.test.d.ts +2 -0
- package/compiled/src/step/parsing/streaming_index_builder.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_index_builder.test.js +107 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts +55 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.js +67 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.test.d.ts +2 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.test.js +66 -0
- package/compiled/src/step/step_model_base.d.ts +9 -3
- package/compiled/src/step/step_model_base.d.ts.map +1 -1
- package/compiled/src/step/step_model_base.js +9 -3
- package/compiled/src/version/version.js +1 -1
- package/compiled/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A random-access, forward-readable byte source for the streaming parser.
|
|
3
|
+
*
|
|
4
|
+
* The streaming index builder (see streaming_index_builder.ts) reads the
|
|
5
|
+
* source sequentially into a small moving window, so a `ByteSource` only has
|
|
6
|
+
* to satisfy positioned reads — it never needs the whole file resident. The
|
|
7
|
+
* in-memory `BufferByteSource` here is for tests and the resident case; a
|
|
8
|
+
* file-descriptor source (node) or an HTTP-Range source (M4) implements the
|
|
9
|
+
* same shape without holding the file in the JS heap.
|
|
10
|
+
*
|
|
11
|
+
* M0 keeps reads synchronous to reuse the existing synchronous parse loop
|
|
12
|
+
* unchanged. The asynchronous variant (network pull-parser) is M4.
|
|
13
|
+
*/
|
|
14
|
+
export interface ByteSource {
|
|
15
|
+
/** Total length of the source in bytes. */
|
|
16
|
+
readonly byteLength: number;
|
|
17
|
+
/**
|
|
18
|
+
* Read up to `length` bytes starting at `offset` into `into` at
|
|
19
|
+
* `intoOffset`, returning the number of bytes actually copied (fewer than
|
|
20
|
+
* `length` only at end of source).
|
|
21
|
+
*
|
|
22
|
+
* @param offset Absolute source offset to read from.
|
|
23
|
+
* @param length Maximum number of bytes to read.
|
|
24
|
+
* @param into Destination buffer.
|
|
25
|
+
* @param intoOffset Offset within `into` to write at.
|
|
26
|
+
* @return {number} The number of bytes copied.
|
|
27
|
+
*/
|
|
28
|
+
read(offset: number, length: number, into: Uint8Array, intoOffset: number): number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A `ByteSource` backed by an in-memory `Uint8Array`. Reads are `subarray`
|
|
32
|
+
* copies into the destination window. Used by tests and the resident path;
|
|
33
|
+
* note it does hold the whole buffer (that residency is the source's, not the
|
|
34
|
+
* parser's — the parser still only touches a window).
|
|
35
|
+
*/
|
|
36
|
+
export declare class BufferByteSource implements ByteSource {
|
|
37
|
+
private readonly buffer;
|
|
38
|
+
/**
|
|
39
|
+
* @param buffer The backing bytes.
|
|
40
|
+
*/
|
|
41
|
+
constructor(buffer: Uint8Array);
|
|
42
|
+
/**
|
|
43
|
+
* @return {number} The buffer length.
|
|
44
|
+
*/
|
|
45
|
+
get byteLength(): number;
|
|
46
|
+
/**
|
|
47
|
+
* @param offset Absolute source offset to read from.
|
|
48
|
+
* @param length Maximum number of bytes to read.
|
|
49
|
+
* @param into Destination buffer.
|
|
50
|
+
* @param intoOffset Offset within `into` to write at.
|
|
51
|
+
* @return {number} The number of bytes copied.
|
|
52
|
+
*/
|
|
53
|
+
read(offset: number, length: number, into: Uint8Array, intoOffset: number): number;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=byte_source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"byte_source.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/byte_source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,UAAU;IAEzB,2CAA2C;IAC3C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAE3B;;;;;;;;;;OAUG;IACH,IAAI,CAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAI,MAAM,CAAA;CACrF;AAED;;;;;GAKG;AACH,qBAAa,gBAAiB,YAAW,UAAU;IAKpC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHpC;;OAEG;gBAC2B,MAAM,EAAE,UAAU;IAEhD;;OAEG;IACH,IAAW,UAAU,IAAI,MAAM,CAE9B;IAED;;;;;;OAMG;IACI,IAAI,CACP,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAI,MAAM;CAYnF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A `ByteSource` backed by an in-memory `Uint8Array`. Reads are `subarray`
|
|
3
|
+
* copies into the destination window. Used by tests and the resident path;
|
|
4
|
+
* note it does hold the whole buffer (that residency is the source's, not the
|
|
5
|
+
* parser's — the parser still only touches a window).
|
|
6
|
+
*/
|
|
7
|
+
export class BufferByteSource {
|
|
8
|
+
/**
|
|
9
|
+
* @param buffer The backing bytes.
|
|
10
|
+
*/
|
|
11
|
+
constructor(buffer) {
|
|
12
|
+
this.buffer = buffer;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* @return {number} The buffer length.
|
|
16
|
+
*/
|
|
17
|
+
get byteLength() {
|
|
18
|
+
return this.buffer.length;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* @param offset Absolute source offset to read from.
|
|
22
|
+
* @param length Maximum number of bytes to read.
|
|
23
|
+
* @param into Destination buffer.
|
|
24
|
+
* @param intoOffset Offset within `into` to write at.
|
|
25
|
+
* @return {number} The number of bytes copied.
|
|
26
|
+
*/
|
|
27
|
+
read(offset, length, into, intoOffset) {
|
|
28
|
+
const end = Math.min(offset + length, this.buffer.length);
|
|
29
|
+
if (end <= offset) {
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
into.set(this.buffer.subarray(offset, end), intoOffset);
|
|
33
|
+
return end - offset;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { StepEntityConstructorAbstract } from "../step_entity_constructor.js";
|
|
2
|
+
import { RecordHandler } from "./streaming_record_dispatcher.js";
|
|
3
|
+
/**
|
|
4
|
+
* A type index built **incrementally** from the streaming parse's per-record
|
|
5
|
+
* events (M2), rather than from the finished element array. Feed its
|
|
6
|
+
* {@link handler} to a {@link StreamingRecordDispatcher} (or directly to
|
|
7
|
+
* `buildIndexStreaming`'s `onRecordIndexed`) and it accumulates, per concrete
|
|
8
|
+
* type, the set of express IDs seen — so the moment parsing reaches a record
|
|
9
|
+
* it is queryable, without waiting for end-of-parse.
|
|
10
|
+
*
|
|
11
|
+
* Queries take entity constructors and expand to their subtype closure via
|
|
12
|
+
* the generated `query` (conway #383), so `expressIDsOfTypes(IfcProduct)`
|
|
13
|
+
* unions every product subtype exactly as the resident model's type index
|
|
14
|
+
* does.
|
|
15
|
+
*
|
|
16
|
+
* Express IDs are held in per-type `Set`s, so the consumer is idempotent
|
|
17
|
+
* under the streaming builder's rare grow-and-restart (records re-fire from
|
|
18
|
+
* localID 0): re-adding an express ID is a no-op. Memory is O(records) — the
|
|
19
|
+
* same order as the element index it mirrors.
|
|
20
|
+
*
|
|
21
|
+
* Scope: membership is keyed on the raw parse `typeID`. External-mapping /
|
|
22
|
+
* complex records (typeID 0) are therefore not attributed to their mapped
|
|
23
|
+
* classes here — resolving those needs the record's `multiMapping`, which the
|
|
24
|
+
* event stream doesn't carry; that's the model's construction-time index. For
|
|
25
|
+
* the overwhelming majority of records (simple, one type each) this index is
|
|
26
|
+
* exact, which the parity test pins.
|
|
27
|
+
*/
|
|
28
|
+
export declare class IncrementalTypeIndex<TypeIDType extends number> {
|
|
29
|
+
/** Concrete typeID → express IDs of records of exactly that type. */
|
|
30
|
+
private readonly byType_;
|
|
31
|
+
/**
|
|
32
|
+
* Record one indexed entity. Bound as {@link handler} for direct use as a
|
|
33
|
+
* dispatcher subscription / `onRecordIndexed` callback.
|
|
34
|
+
*
|
|
35
|
+
* @param localID Unused (kept for the RecordHandler shape).
|
|
36
|
+
* @param expressID The record's express ID.
|
|
37
|
+
* @param typeID The record's concrete type ID (undefined / 0 records are
|
|
38
|
+
* ignored — they carry no concrete queryable type here).
|
|
39
|
+
*/
|
|
40
|
+
readonly handler: RecordHandler<TypeIDType>;
|
|
41
|
+
/**
|
|
42
|
+
* The distinct concrete type IDs seen so far.
|
|
43
|
+
*
|
|
44
|
+
* @return {IterableIterator<TypeIDType>} The concrete types.
|
|
45
|
+
*/
|
|
46
|
+
concreteTypes(): IterableIterator<TypeIDType>;
|
|
47
|
+
/**
|
|
48
|
+
* Lazily iterate the express IDs of all records of the given types
|
|
49
|
+
* (including subtypes).
|
|
50
|
+
*
|
|
51
|
+
* @param types The entity constructors to query (subtype closures unioned).
|
|
52
|
+
* @return {IterableIterator<number>} Express IDs of matching records.
|
|
53
|
+
* @yields {number} Each matching express ID.
|
|
54
|
+
*/
|
|
55
|
+
expressIDsOfTypes(...types: StepEntityConstructorAbstract<TypeIDType>[]): IterableIterator<number>;
|
|
56
|
+
/**
|
|
57
|
+
* Count records of the given types (including subtypes) seen so far.
|
|
58
|
+
*
|
|
59
|
+
* @param types The entity constructors to count.
|
|
60
|
+
* @return {number} The number of matching records.
|
|
61
|
+
*/
|
|
62
|
+
count(...types: StepEntityConstructorAbstract<TypeIDType>[]): number;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=incremental_type_index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"incremental_type_index.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/incremental_type_index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAA;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAG7D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,oBAAoB,CAAC,UAAU,SAAS,MAAM;IAEzD,qEAAqE;IACrE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAE7D;;;;;;;;OAQG;IACH,SAAgB,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,CAe/C;IAEH;;;;OAIG;IACI,aAAa,IAAI,gBAAgB,CAAC,UAAU,CAAC;IAIpD;;;;;;;OAOG;IACK,iBAAiB,CACrB,GAAG,KAAK,EAAE,6BAA6B,CAAC,UAAU,CAAC,EAAE,GACrD,gBAAgB,CAAC,MAAM,CAAC;IAc5B;;;;;OAKG;IACI,KAAK,CAAE,GAAG,KAAK,EAAE,6BAA6B,CAAC,UAAU,CAAC,EAAE,GAAI,MAAM;CAa9E"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A type index built **incrementally** from the streaming parse's per-record
|
|
3
|
+
* events (M2), rather than from the finished element array. Feed its
|
|
4
|
+
* {@link handler} to a {@link StreamingRecordDispatcher} (or directly to
|
|
5
|
+
* `buildIndexStreaming`'s `onRecordIndexed`) and it accumulates, per concrete
|
|
6
|
+
* type, the set of express IDs seen — so the moment parsing reaches a record
|
|
7
|
+
* it is queryable, without waiting for end-of-parse.
|
|
8
|
+
*
|
|
9
|
+
* Queries take entity constructors and expand to their subtype closure via
|
|
10
|
+
* the generated `query` (conway #383), so `expressIDsOfTypes(IfcProduct)`
|
|
11
|
+
* unions every product subtype exactly as the resident model's type index
|
|
12
|
+
* does.
|
|
13
|
+
*
|
|
14
|
+
* Express IDs are held in per-type `Set`s, so the consumer is idempotent
|
|
15
|
+
* under the streaming builder's rare grow-and-restart (records re-fire from
|
|
16
|
+
* localID 0): re-adding an express ID is a no-op. Memory is O(records) — the
|
|
17
|
+
* same order as the element index it mirrors.
|
|
18
|
+
*
|
|
19
|
+
* Scope: membership is keyed on the raw parse `typeID`. External-mapping /
|
|
20
|
+
* complex records (typeID 0) are therefore not attributed to their mapped
|
|
21
|
+
* classes here — resolving those needs the record's `multiMapping`, which the
|
|
22
|
+
* event stream doesn't carry; that's the model's construction-time index. For
|
|
23
|
+
* the overwhelming majority of records (simple, one type each) this index is
|
|
24
|
+
* exact, which the parity test pins.
|
|
25
|
+
*/
|
|
26
|
+
export class IncrementalTypeIndex {
|
|
27
|
+
constructor() {
|
|
28
|
+
/** Concrete typeID → express IDs of records of exactly that type. */
|
|
29
|
+
this.byType_ = new Map();
|
|
30
|
+
/**
|
|
31
|
+
* Record one indexed entity. Bound as {@link handler} for direct use as a
|
|
32
|
+
* dispatcher subscription / `onRecordIndexed` callback.
|
|
33
|
+
*
|
|
34
|
+
* @param localID Unused (kept for the RecordHandler shape).
|
|
35
|
+
* @param expressID The record's express ID.
|
|
36
|
+
* @param typeID The record's concrete type ID (undefined / 0 records are
|
|
37
|
+
* ignored — they carry no concrete queryable type here).
|
|
38
|
+
*/
|
|
39
|
+
this.handler = (localID, expressID, typeID) => {
|
|
40
|
+
if (typeID === void 0) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
let ids = this.byType_.get(typeID);
|
|
44
|
+
if (ids === void 0) {
|
|
45
|
+
ids = new Set();
|
|
46
|
+
this.byType_.set(typeID, ids);
|
|
47
|
+
}
|
|
48
|
+
ids.add(expressID);
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The distinct concrete type IDs seen so far.
|
|
53
|
+
*
|
|
54
|
+
* @return {IterableIterator<TypeIDType>} The concrete types.
|
|
55
|
+
*/
|
|
56
|
+
concreteTypes() {
|
|
57
|
+
return this.byType_.keys();
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Lazily iterate the express IDs of all records of the given types
|
|
61
|
+
* (including subtypes).
|
|
62
|
+
*
|
|
63
|
+
* @param types The entity constructors to query (subtype closures unioned).
|
|
64
|
+
* @return {IterableIterator<number>} Express IDs of matching records.
|
|
65
|
+
* @yields {number} Each matching express ID.
|
|
66
|
+
*/
|
|
67
|
+
*expressIDsOfTypes(...types) {
|
|
68
|
+
const typeSet = types.length === 1 ? types[0].query :
|
|
69
|
+
new Set(types.flatMap((type) => type.query));
|
|
70
|
+
for (const typeID of typeSet) {
|
|
71
|
+
const ids = this.byType_.get(typeID);
|
|
72
|
+
if (ids !== void 0) {
|
|
73
|
+
yield* ids;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Count records of the given types (including subtypes) seen so far.
|
|
79
|
+
*
|
|
80
|
+
* @param types The entity constructors to count.
|
|
81
|
+
* @return {number} The number of matching records.
|
|
82
|
+
*/
|
|
83
|
+
count(...types) {
|
|
84
|
+
const typeSet = types.length === 1 ? types[0].query :
|
|
85
|
+
new Set(types.flatMap((type) => type.query));
|
|
86
|
+
let total = 0;
|
|
87
|
+
for (const typeID of typeSet) {
|
|
88
|
+
total += this.byType_.get(typeID)?.size ?? 0;
|
|
89
|
+
}
|
|
90
|
+
return total;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"incremental_type_index.test.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/incremental_type_index.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/* eslint-disable no-magic-numbers */
|
|
2
|
+
// M2b: a type index built incrementally from the streaming parse's record
|
|
3
|
+
// events must, once parsing finishes, hold the same membership as the
|
|
4
|
+
// resident model's type index — for every queried type (and its subtypes).
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import { beforeAll, describe, expect, test } from "@jest/globals";
|
|
7
|
+
import ParsingBuffer from "../../parsing/parsing_buffer.js";
|
|
8
|
+
import IfcStepParser from "../../ifc/ifc_step_parser.js";
|
|
9
|
+
import { BufferByteSource } from "./byte_source.js";
|
|
10
|
+
import { buildIndexStreaming } from "./streaming_index_builder.js";
|
|
11
|
+
import { IncrementalTypeIndex } from "./incremental_type_index.js";
|
|
12
|
+
import { StreamingRecordDispatcher } from "./streaming_record_dispatcher.js";
|
|
13
|
+
import { ParseResult } from "./step_parser.js";
|
|
14
|
+
import { IfcRoot, IfcProduct, IfcWall, IfcPropertySet } from "../../ifc/ifc4_gen/index.js";
|
|
15
|
+
let bytes;
|
|
16
|
+
let model;
|
|
17
|
+
beforeAll(() => {
|
|
18
|
+
bytes = new Uint8Array(fs.readFileSync("data/index.ifc"));
|
|
19
|
+
const input = new ParsingBuffer(bytes);
|
|
20
|
+
IfcStepParser.Instance.parseHeader(input);
|
|
21
|
+
model = IfcStepParser.Instance.parseDataToModel(input)[1];
|
|
22
|
+
});
|
|
23
|
+
describe("IncrementalTypeIndex", () => {
|
|
24
|
+
/**
|
|
25
|
+
* Stream index.ifc, feeding an IncrementalTypeIndex, and return it.
|
|
26
|
+
*
|
|
27
|
+
* @return {IncrementalTypeIndex} The populated index.
|
|
28
|
+
*/
|
|
29
|
+
function streamed() {
|
|
30
|
+
const index = new IncrementalTypeIndex();
|
|
31
|
+
const dispatcher = new StreamingRecordDispatcher();
|
|
32
|
+
dispatcher.onAnyRecord(index.handler);
|
|
33
|
+
const r = buildIndexStreaming(new BufferByteSource(bytes), IfcStepParser.Instance, 4 * 1024, dispatcher.onRecordIndexed);
|
|
34
|
+
expect(r.result).toBe(ParseResult.COMPLETE);
|
|
35
|
+
return index;
|
|
36
|
+
}
|
|
37
|
+
test.each([
|
|
38
|
+
["IfcRoot", IfcRoot],
|
|
39
|
+
["IfcProduct", IfcProduct],
|
|
40
|
+
["IfcWall", IfcWall],
|
|
41
|
+
["IfcPropertySet", IfcPropertySet],
|
|
42
|
+
])("membership matches the resident type index for %s", (_name, ctor) => {
|
|
43
|
+
const index = streamed();
|
|
44
|
+
const incremental = new Set(index.expressIDsOfTypes(ctor));
|
|
45
|
+
const resident = new Set(model.expressIDsOfTypes(ctor));
|
|
46
|
+
expect(incremental).toEqual(resident);
|
|
47
|
+
expect(index.count(ctor)).toBe(resident.size);
|
|
48
|
+
});
|
|
49
|
+
test("a multi-type query unions the subtype closures", () => {
|
|
50
|
+
const index = streamed();
|
|
51
|
+
const incremental = new Set(index.expressIDsOfTypes(IfcWall, IfcPropertySet));
|
|
52
|
+
const resident = new Set(model.expressIDsOfTypes(IfcWall, IfcPropertySet));
|
|
53
|
+
expect(incremental).toEqual(resident);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -116,6 +116,25 @@ export default class StepParser<TypeIDType> extends StepHeaderParser {
|
|
|
116
116
|
* @return {BlockParseResult} The parsing result, including the index and result enum.
|
|
117
117
|
*/
|
|
118
118
|
parseDataBlock(input: ParsingBuffer, onProgress?: ParseProgressCallback): BlockParseResult<TypeIDType>;
|
|
119
|
+
/**
|
|
120
|
+
* Streaming driver over parseDataBlockIncremental: identical parse (same
|
|
121
|
+
* generator body) but invokes `onRecordBoundary` at every top-level record
|
|
122
|
+
* boundary so a caller feeding the parser from a moving window can slide
|
|
123
|
+
* that window forward while the rewind stack is empty. See
|
|
124
|
+
* streaming_index_builder.ts for the coordinator that owns the window.
|
|
125
|
+
*
|
|
126
|
+
* @param input The input parsing buffer, positioned at the data section.
|
|
127
|
+
* @param onRecordBoundary Called at each top-level record boundary with the
|
|
128
|
+
* buffer; the callback may rebase the buffer's window in place.
|
|
129
|
+
* @param onRecordIndexed Called as each top-level record is indexed, with
|
|
130
|
+
* its localID, expressID and typeID (0 for external-mapping records) — the
|
|
131
|
+
* seam for incremental semantic consumers (type index, roots registry,
|
|
132
|
+
* names skeleton). Must be synchronous and cheap; expensive work belongs on
|
|
133
|
+
* a demand queue, not the parse path.
|
|
134
|
+
* @param onProgress Optional byte-cursor progress callback.
|
|
135
|
+
* @return {BlockParseResult} The parsing result, including the index and result enum.
|
|
136
|
+
*/
|
|
137
|
+
parseDataBlockStreamed(input: ParsingBuffer, onRecordBoundary: (input: ParsingBuffer) => void, onRecordIndexed?: (localID: number, expressID: number, typeID: TypeIDType | undefined) => void, onProgress?: ParseProgressCallback): BlockParseResult<TypeIDType>;
|
|
119
138
|
/**
|
|
120
139
|
* Cooperative variant of parseDataBlock: identical parse (same generator
|
|
121
140
|
* body), but periodically awaits a macrotask so the event loop can run —
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"step_parser.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/step_parser.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"step_parser.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/step_parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -310,6 +310,34 @@ export default class StepParser extends StepHeaderParser {
|
|
|
310
310
|
onProgress?.(next.value);
|
|
311
311
|
}
|
|
312
312
|
}
|
|
313
|
+
/**
|
|
314
|
+
* Streaming driver over parseDataBlockIncremental: identical parse (same
|
|
315
|
+
* generator body) but invokes `onRecordBoundary` at every top-level record
|
|
316
|
+
* boundary so a caller feeding the parser from a moving window can slide
|
|
317
|
+
* that window forward while the rewind stack is empty. See
|
|
318
|
+
* streaming_index_builder.ts for the coordinator that owns the window.
|
|
319
|
+
*
|
|
320
|
+
* @param input The input parsing buffer, positioned at the data section.
|
|
321
|
+
* @param onRecordBoundary Called at each top-level record boundary with the
|
|
322
|
+
* buffer; the callback may rebase the buffer's window in place.
|
|
323
|
+
* @param onRecordIndexed Called as each top-level record is indexed, with
|
|
324
|
+
* its localID, expressID and typeID (0 for external-mapping records) — the
|
|
325
|
+
* seam for incremental semantic consumers (type index, roots registry,
|
|
326
|
+
* names skeleton). Must be synchronous and cheap; expensive work belongs on
|
|
327
|
+
* a demand queue, not the parse path.
|
|
328
|
+
* @param onProgress Optional byte-cursor progress callback.
|
|
329
|
+
* @return {BlockParseResult} The parsing result, including the index and result enum.
|
|
330
|
+
*/
|
|
331
|
+
parseDataBlockStreamed(input, onRecordBoundary, onRecordIndexed, onProgress) {
|
|
332
|
+
const parser = this.parseDataBlockIncremental(input, onRecordBoundary, onRecordIndexed);
|
|
333
|
+
while (true) {
|
|
334
|
+
const next = parser.next();
|
|
335
|
+
if (next.done === true) {
|
|
336
|
+
return next.value;
|
|
337
|
+
}
|
|
338
|
+
onProgress?.(next.value);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
313
341
|
/**
|
|
314
342
|
* Cooperative variant of parseDataBlock: identical parse (same generator
|
|
315
343
|
* body), but periodically awaits a macrotask so the event loop can run —
|
|
@@ -347,7 +375,7 @@ export default class StepParser extends StepHeaderParser {
|
|
|
347
375
|
* @yields {number} The current byte cursor within the input buffer.
|
|
348
376
|
* @return {BlockParseResult} The parsing result, including the index and result enum.
|
|
349
377
|
*/
|
|
350
|
-
*parseDataBlockIncremental(input) {
|
|
378
|
+
*parseDataBlockIncremental(input, onRecordBoundary, onRecordIndexed) {
|
|
351
379
|
const indexResult = { elements: [] };
|
|
352
380
|
const match = input.match;
|
|
353
381
|
const comment = () => match(commentParser);
|
|
@@ -394,7 +422,10 @@ export default class StepParser extends StepHeaderParser {
|
|
|
394
422
|
return syntaxError();
|
|
395
423
|
}
|
|
396
424
|
whitespace();
|
|
397
|
-
|
|
425
|
+
// File-absolute (== input.cursor when initialOffset is 0, i.e. every
|
|
426
|
+
// resident parse; file-absolute under a streaming moving window so the
|
|
427
|
+
// recorded address/length stay stable as the window slides).
|
|
428
|
+
const startElement = input.address;
|
|
398
429
|
let stackDepth = 1;
|
|
399
430
|
const savedInlineElements = inlineElements;
|
|
400
431
|
inlineElements = void 0;
|
|
@@ -492,6 +523,11 @@ export default class StepParser extends StepHeaderParser {
|
|
|
492
523
|
if ((++parsedElementCount & PARSE_PROGRESS_ELEMENT_MASK) === 0) {
|
|
493
524
|
yield input.cursor;
|
|
494
525
|
}
|
|
526
|
+
// Top-level record boundary: the rewind stack is empty and the cursor
|
|
527
|
+
// sits at the next record's leading whitespace/`#`. A streaming driver
|
|
528
|
+
// uses this to slide its moving window forward (see
|
|
529
|
+
// streaming_index_builder.ts). No-op on the resident path.
|
|
530
|
+
onRecordBoundary?.(input);
|
|
495
531
|
if (!charws(HASH)) {
|
|
496
532
|
if (tokenws(END_SECTION)) {
|
|
497
533
|
return parseResult(ParseResult.COMPLETE);
|
|
@@ -516,7 +552,10 @@ export default class StepParser extends StepHeaderParser {
|
|
|
516
552
|
}
|
|
517
553
|
whitespace();
|
|
518
554
|
inlineElements = void 0;
|
|
519
|
-
|
|
555
|
+
// File-absolute (== input.cursor when initialOffset is 0, i.e. every
|
|
556
|
+
// resident parse; file-absolute under a streaming moving window so the
|
|
557
|
+
// recorded address/length stay stable as the window slides).
|
|
558
|
+
const startElement = input.address;
|
|
520
559
|
// todo, loop and read inline then add them to a special "External Mapping" node.
|
|
521
560
|
while (!charws(CLOSE_PAREN)) {
|
|
522
561
|
input.begin();
|
|
@@ -530,6 +569,7 @@ export default class StepParser extends StepHeaderParser {
|
|
|
530
569
|
if (!charws(SEMICOLON)) {
|
|
531
570
|
return syntaxError();
|
|
532
571
|
}
|
|
572
|
+
onRecordIndexed?.(indexResult.elements.length, expressID, 0);
|
|
533
573
|
indexResult.elements.push({
|
|
534
574
|
address: startElement,
|
|
535
575
|
length: input.address - startElement,
|
|
@@ -547,7 +587,10 @@ export default class StepParser extends StepHeaderParser {
|
|
|
547
587
|
return syntaxError();
|
|
548
588
|
}
|
|
549
589
|
whitespace();
|
|
550
|
-
|
|
590
|
+
// File-absolute (== input.cursor when initialOffset is 0, i.e. every
|
|
591
|
+
// resident parse; file-absolute under a streaming moving window so the
|
|
592
|
+
// recorded address/length stay stable as the window slides).
|
|
593
|
+
const startElement = input.address;
|
|
551
594
|
let stackDepth = 1;
|
|
552
595
|
inlineElements = void 0;
|
|
553
596
|
while (stackDepth > 0) {
|
|
@@ -620,6 +663,7 @@ export default class StepParser extends StepHeaderParser {
|
|
|
620
663
|
if (!charws(SEMICOLON)) {
|
|
621
664
|
return syntaxError();
|
|
622
665
|
}
|
|
666
|
+
onRecordIndexed?.(indexResult.elements.length, expressID, foundItem);
|
|
623
667
|
indexResult.elements.push({
|
|
624
668
|
address: startElement,
|
|
625
669
|
length: input.address - startElement,
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { ByteSource } from "./byte_source.js";
|
|
2
|
+
import StepParser, { ParseResult, StepHeader, StepIndexEntry } from "./step_parser.js";
|
|
3
|
+
/**
|
|
4
|
+
* Diagnostics from a streaming index build — how hard the moving window had
|
|
5
|
+
* to work, so a pool-size sweep can compare cost against a resident parse.
|
|
6
|
+
*/
|
|
7
|
+
export interface StreamingIndexStats {
|
|
8
|
+
/** Target window size in bytes (the pool). */
|
|
9
|
+
pool: number;
|
|
10
|
+
/** Physical window buffer size actually used (grows past `pool` only if a
|
|
11
|
+
* single record exceeds the pool). */
|
|
12
|
+
windowBytes: number;
|
|
13
|
+
/** Number of times the window slid forward. */
|
|
14
|
+
slides: number;
|
|
15
|
+
/** Largest single top-level record observed, in bytes. */
|
|
16
|
+
maxRecordLen: number;
|
|
17
|
+
/** Total bytes read from the source (≈ file size + re-reads on growth). */
|
|
18
|
+
bytesRead: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The output of a streaming index build: the same element index a resident
|
|
22
|
+
* `parseDataBlock` produces, plus the header and window diagnostics.
|
|
23
|
+
*/
|
|
24
|
+
export interface StreamingIndexResult<TypeIDType> {
|
|
25
|
+
header: StepHeader;
|
|
26
|
+
elements: StepIndexEntry<TypeIDType>[];
|
|
27
|
+
result: ParseResult;
|
|
28
|
+
stats: StreamingIndexStats;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Build the entity index by streaming a `ByteSource` through a fixed-size
|
|
32
|
+
* moving window, instead of parsing one resident buffer. The parse loop is
|
|
33
|
+
* byte-for-byte the resident one (`StepParser.parseDataBlockStreamed` drives
|
|
34
|
+
* the same generator); this coordinator only owns the window: it fills it,
|
|
35
|
+
* parses the header from the first fill, then slides the window forward at
|
|
36
|
+
* top-level record boundaries as the parser advances.
|
|
37
|
+
*
|
|
38
|
+
* Because the parser records file-absolute addresses and its rewind stack is
|
|
39
|
+
* empty at every top-level boundary, sliding there is transparent: the
|
|
40
|
+
* unconsumed tail is copied to the front, fresh bytes are appended, and the
|
|
41
|
+
* buffer is rebased so `address` keeps its file-absolute value. Peak JS heap
|
|
42
|
+
* for the index build is therefore `window + index columns`, independent of
|
|
43
|
+
* file size.
|
|
44
|
+
*
|
|
45
|
+
* The window slides only once the cursor passes `pool / 2`, bounding the
|
|
46
|
+
* memmove frequency; a record up to `pool / 2` bytes always fits after a
|
|
47
|
+
* slide. If a single record exceeds that (never on the current corpus, whose
|
|
48
|
+
* largest STEP record is ~25 KB), the whole parse restarts from the
|
|
49
|
+
* beginning with the window doubled, and repeats until every record fits —
|
|
50
|
+
* correctness over the pathological case, at the cost of a re-scan. (M1's
|
|
51
|
+
* production path will instead grow in place / restart from the last
|
|
52
|
+
* boundary; from-scratch keeps the spike simple.)
|
|
53
|
+
*
|
|
54
|
+
* @param source The byte source.
|
|
55
|
+
* @param parser The STEP parser (typed to the schema).
|
|
56
|
+
* @param pool Target window size in bytes.
|
|
57
|
+
* @param onRecordIndexed Optional per-record event, invoked live as each
|
|
58
|
+
* top-level record is indexed with its (localID, expressID, typeID) — the
|
|
59
|
+
* seam for incremental semantic consumers (M2). localIDs are dense and
|
|
60
|
+
* assigned in parse order from 0. On the rare grow-and-restart (a single
|
|
61
|
+
* record larger than the window — never on real files, whose largest STEP
|
|
62
|
+
* record is ~25 KB), the parse re-runs from the start and records re-fire
|
|
63
|
+
* from localID 0; consumers must therefore be idempotent by localID /
|
|
64
|
+
* expressID (the standard consumers — type index keyed by localID, roots
|
|
65
|
+
* registry keyed by expressID — are). Must be synchronous and cheap;
|
|
66
|
+
* expensive work belongs on a demand queue, not the parse path.
|
|
67
|
+
* @return {StreamingIndexResult} The index, header, result and diagnostics.
|
|
68
|
+
*/
|
|
69
|
+
export declare function buildIndexStreaming<TypeIDType>(source: ByteSource, parser: StepParser<TypeIDType>, pool: number, onRecordIndexed?: (localID: number, expressID: number, typeID: TypeIDType | undefined) => void): StreamingIndexResult<TypeIDType>;
|
|
70
|
+
//# sourceMappingURL=streaming_index_builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaming_index_builder.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/streaming_index_builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,UAAU,EAAE,EACjB,WAAW,EACX,UAAU,EACV,cAAc,EACf,MAAM,eAAe,CAAA;AAGtB;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAElC,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAA;IAEZ;0CACsC;IACtC,WAAW,EAAE,MAAM,CAAA;IAEnB,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAA;IAEd,0DAA0D;IAC1D,YAAY,EAAE,MAAM,CAAA;IAEpB,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAA;CAClB;AAGD;;;GAGG;AACH,MAAM,WAAW,oBAAoB,CAAC,UAAU;IAC9C,MAAM,EAAE,UAAU,CAAA;IAClB,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,EAAE,CAAA;IACtC,MAAM,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,mBAAmB,CAAA;CAC3B;AAGD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAC1C,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC,EAC9B,IAAI,EAAE,MAAM,EACZ,eAAe,CAAC,EACd,CAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,SAAS,KAAM,IAAI,GAChF,oBAAoB,CAAC,UAAU,CAAC,CA4GnC"}
|