@bldrs-ai/conway 1.389.1221 → 1.394.1504
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/README.md +36 -22
- 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/dependencies/conway-geom/interface/conway_geometry.d.ts +19 -0
- package/compiled/dependencies/conway-geom/interface/conway_geometry.d.ts.map +1 -1
- package/compiled/dependencies/conway-geom/interface/conway_geometry.js +17 -0
- package/compiled/dependencies/conway-geom/interface/parameters/surface_object.d.ts +6 -0
- package/compiled/dependencies/conway-geom/interface/parameters/surface_object.d.ts.map +1 -1
- package/compiled/examples/browser-bundled.cjs +1569 -51
- package/compiled/examples/cli-bundled.cjs +2790 -436
- package/compiled/examples/cli-step-bundled.cjs +1904 -229
- package/compiled/examples/validator-bundled.cjs +1569 -51
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_curve.gen.d.ts +2 -2
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_curve.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_curve.gen.js +2 -2
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_surface.gen.d.ts +3 -3
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_surface.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_surface.gen.js +3 -3
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/composite_curve.gen.d.ts +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/composite_curve.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/composite_curve.gen.js +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_2d.gen.d.ts +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_2d.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_2d.gen.js +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_3d.gen.d.ts +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_3d.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_3d.gen.js +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_surface.gen.d.ts +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_surface.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_surface.gen.js +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/presentation_style_assignment.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/presentation_style_assignment.gen.js +2 -2
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/schema_ap214.gen.js +11 -11
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/shape_aspect.gen.d.ts +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/shape_aspect.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/shape_aspect.gen.js +1 -1
- package/compiled/src/AP214E3_2010/ap214_command_line_main.js +7 -3
- package/compiled/src/AP214E3_2010/ap214_geometry_extraction.d.ts +181 -7
- package/compiled/src/AP214E3_2010/ap214_geometry_extraction.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/ap214_geometry_extraction.js +906 -137
- package/compiled/src/AP214E3_2010/ap214_geometry_extraction.test.js +10 -2
- package/compiled/src/AP214E3_2010/ap214_logical_attribute.test.d.ts +2 -0
- package/compiled/src/AP214E3_2010/ap214_logical_attribute.test.d.ts.map +1 -0
- package/compiled/src/AP214E3_2010/ap214_logical_attribute.test.js +114 -0
- package/compiled/src/AP214E3_2010/ap214_model_geometry.d.ts +6 -0
- package/compiled/src/AP214E3_2010/ap214_model_geometry.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/ap214_model_geometry.js +9 -0
- package/compiled/src/AP214E3_2010/ap214_pcurve_basis_surfaces.test.d.ts +2 -0
- package/compiled/src/AP214E3_2010/ap214_pcurve_basis_surfaces.test.d.ts.map +1 -0
- package/compiled/src/AP214E3_2010/ap214_pcurve_basis_surfaces.test.js +233 -0
- package/compiled/src/AP214E3_2010/ap214_sphere_vertex_loop.test.d.ts +2 -0
- package/compiled/src/AP214E3_2010/ap214_sphere_vertex_loop.test.d.ts.map +1 -0
- package/compiled/src/AP214E3_2010/ap214_sphere_vertex_loop.test.js +147 -0
- package/compiled/src/AP214E3_2010/ap214_step_model.d.ts +2 -1
- package/compiled/src/AP214E3_2010/ap214_step_model.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/ap214_step_model.js +1 -1
- package/compiled/src/AP214E3_2010/ap214_typed_select_enum.test.d.ts +2 -0
- package/compiled/src/AP214E3_2010/ap214_typed_select_enum.test.d.ts.map +1 -0
- package/compiled/src/AP214E3_2010/ap214_typed_select_enum.test.js +65 -0
- package/compiled/src/AP214E3_2010/ap214_unit_scale.test.d.ts +2 -0
- package/compiled/src/AP214E3_2010/ap214_unit_scale.test.d.ts.map +1 -0
- package/compiled/src/AP214E3_2010/ap214_unit_scale.test.js +111 -0
- package/compiled/src/compat/web-ifc/ap214_streamed_open.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/ap214_streamed_open.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/ap214_streamed_open.test.js +190 -0
- package/compiled/src/compat/web-ifc/coordination_export_order.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/coordination_export_order.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/coordination_export_order.test.js +110 -0
- package/compiled/src/compat/web-ifc/coordination_f64.d.ts +165 -0
- package/compiled/src/compat/web-ifc/coordination_f64.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/coordination_f64.js +286 -0
- package/compiled/src/compat/web-ifc/coordination_f64.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/coordination_f64.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/coordination_f64.test.js +225 -0
- package/compiled/src/compat/web-ifc/ifc_api.d.ts +154 -0
- package/compiled/src/compat/web-ifc/ifc_api.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api.js +211 -3
- package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.js +288 -0
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts +39 -0
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.d.ts +30 -0
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.js +83 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.js +383 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.js +124 -0
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.d.ts +132 -0
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.js +488 -92
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts +268 -0
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.js +996 -149
- package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.js +129 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.d.ts +134 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.js +933 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.test.js +467 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.d.ts +187 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.js +524 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.test.js +234 -0
- package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts +306 -0
- package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/streamed_preview_channel.js +580 -0
- package/compiled/src/compat/web-ifc/web_wasm_directory.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/web_wasm_directory.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/web_wasm_directory.test.js +22 -0
- package/compiled/src/core/composed_model_skeleton.d.ts +63 -0
- package/compiled/src/core/composed_model_skeleton.d.ts.map +1 -0
- package/compiled/src/core/composed_model_skeleton.js +66 -0
- package/compiled/src/core/composed_model_skeleton.test.d.ts +2 -0
- package/compiled/src/core/composed_model_skeleton.test.d.ts.map +1 -0
- package/compiled/src/core/composed_model_skeleton.test.js +69 -0
- package/compiled/src/core/demand_geometry_queue.d.ts +147 -0
- package/compiled/src/core/demand_geometry_queue.d.ts.map +1 -0
- package/compiled/src/core/demand_geometry_queue.js +223 -0
- package/compiled/src/core/demand_geometry_queue.test.d.ts +2 -0
- package/compiled/src/core/demand_geometry_queue.test.d.ts.map +1 -0
- package/compiled/src/core/demand_geometry_queue.test.js +133 -0
- package/compiled/src/core/demand_residency_pump.d.ts +93 -0
- package/compiled/src/core/demand_residency_pump.d.ts.map +1 -0
- package/compiled/src/core/demand_residency_pump.js +120 -0
- package/compiled/src/core/demand_residency_pump.test.d.ts +2 -0
- package/compiled/src/core/demand_residency_pump.test.d.ts.map +1 -0
- package/compiled/src/core/demand_residency_pump.test.js +148 -0
- package/compiled/src/core/geometry_tile_bindings.d.ts +110 -0
- package/compiled/src/core/geometry_tile_bindings.d.ts.map +1 -0
- package/compiled/src/core/geometry_tile_bindings.js +76 -0
- package/compiled/src/core/geometry_tile_bindings.test.d.ts +2 -0
- package/compiled/src/core/geometry_tile_bindings.test.d.ts.map +1 -0
- package/compiled/src/core/geometry_tile_bindings.test.js +211 -0
- package/compiled/src/core/geometry_tile_pool.d.ts +99 -0
- package/compiled/src/core/geometry_tile_pool.d.ts.map +1 -0
- package/compiled/src/core/geometry_tile_pool.js +104 -0
- package/compiled/src/core/geometry_tile_pool.test.d.ts +2 -0
- package/compiled/src/core/geometry_tile_pool.test.d.ts.map +1 -0
- package/compiled/src/core/geometry_tile_pool.test.js +180 -0
- package/compiled/src/core/mem/chunked_pool.d.ts +116 -0
- package/compiled/src/core/mem/chunked_pool.d.ts.map +1 -0
- package/compiled/src/core/mem/chunked_pool.js +149 -0
- package/compiled/src/core/mem/chunked_pool.test.d.ts +2 -0
- package/compiled/src/core/mem/chunked_pool.test.d.ts.map +1 -0
- package/compiled/src/core/mem/chunked_pool.test.js +63 -0
- package/compiled/src/core/mem/shared_asset_pool.d.ts +82 -0
- package/compiled/src/core/mem/shared_asset_pool.d.ts.map +1 -0
- package/compiled/src/core/mem/shared_asset_pool.js +113 -0
- package/compiled/src/core/mem/shared_asset_pool.test.d.ts +2 -0
- package/compiled/src/core/mem/shared_asset_pool.test.d.ts.map +1 -0
- package/compiled/src/core/mem/shared_asset_pool.test.js +49 -0
- package/compiled/src/core/model_registry.d.ts +87 -0
- package/compiled/src/core/model_registry.d.ts.map +1 -0
- package/compiled/src/core/model_registry.js +101 -0
- package/compiled/src/core/model_registry.test.d.ts +2 -0
- package/compiled/src/core/model_registry.test.d.ts.map +1 -0
- package/compiled/src/core/model_registry.test.js +60 -0
- package/compiled/src/core/model_uri.d.ts +57 -0
- package/compiled/src/core/model_uri.d.ts.map +1 -0
- package/compiled/src/core/model_uri.js +101 -0
- package/compiled/src/core/model_uri.test.d.ts +2 -0
- package/compiled/src/core/model_uri.test.d.ts.map +1 -0
- package/compiled/src/core/model_uri.test.js +49 -0
- package/compiled/src/core/progress.d.ts +16 -2
- package/compiled/src/core/progress.d.ts.map +1 -1
- package/compiled/src/core/progress.js +31 -5
- package/compiled/src/core/progress.test.js +11 -2
- package/compiled/src/core/progress_log.d.ts +1 -0
- package/compiled/src/core/progress_log.d.ts.map +1 -1
- package/compiled/src/core/progress_log.js +7 -2
- package/compiled/src/core/progress_log.test.js +21 -0
- package/compiled/src/core/shared_byte_budget.d.ts +60 -0
- package/compiled/src/core/shared_byte_budget.d.ts.map +1 -0
- package/compiled/src/core/shared_byte_budget.js +85 -0
- package/compiled/src/core/shared_byte_budget.test.d.ts +2 -0
- package/compiled/src/core/shared_byte_budget.test.d.ts.map +1 -0
- package/compiled/src/core/shared_byte_budget.test.js +55 -0
- package/compiled/src/core/wasm_heap.d.ts +208 -0
- package/compiled/src/core/wasm_heap.d.ts.map +1 -0
- package/compiled/src/core/wasm_heap.js +417 -0
- package/compiled/src/core/wasm_heap.test.d.ts +2 -0
- package/compiled/src/core/wasm_heap.test.d.ts.map +1 -0
- package/compiled/src/core/wasm_heap.test.js +546 -0
- package/compiled/src/demand/index.d.ts +23 -0
- package/compiled/src/demand/index.d.ts.map +1 -0
- package/compiled/src/demand/index.js +22 -0
- package/compiled/src/ifc/ifc4_gen/IfcLogical.gen.d.ts +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcLogical.gen.d.ts.map +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcLogical.gen.js +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcPresentationStyleAssignment.gen.d.ts.map +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcPresentationStyleAssignment.gen.js +2 -2
- package/compiled/src/ifc/ifc4_gen/IfcRelInterferesElements.gen.d.ts +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcRelInterferesElements.gen.d.ts.map +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcRelInterferesElements.gen.js +1 -1
- package/compiled/src/ifc/ifc4_gen/schema_ifc.gen.js +2 -2
- package/compiled/src/ifc/ifc_demand_extraction.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_demand_extraction.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_demand_extraction.test.js +251 -0
- package/compiled/src/ifc/ifc_geometry_extraction.d.ts +367 -6
- package/compiled/src/ifc/ifc_geometry_extraction.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_geometry_extraction.js +1322 -389
- package/compiled/src/ifc/ifc_grid_placement.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_grid_placement.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_grid_placement.test.js +261 -0
- package/compiled/src/ifc/ifc_model_geometry.d.ts +12 -0
- package/compiled/src/ifc/ifc_model_geometry.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_model_geometry.js +15 -0
- package/compiled/src/ifc/ifc_regression_batch_main.js +210 -12
- package/compiled/src/ifc/ifc_spatial_skeleton.d.ts +145 -0
- package/compiled/src/ifc/ifc_spatial_skeleton.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_spatial_skeleton.js +266 -0
- package/compiled/src/ifc/ifc_spatial_skeleton.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_spatial_skeleton.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_spatial_skeleton.test.js +199 -0
- package/compiled/src/ifc/ifc_step_model.d.ts +6 -2
- package/compiled/src/ifc/ifc_step_model.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_step_model.js +6 -4
- package/compiled/src/ifc/ifc_step_parser.d.ts +58 -0
- package/compiled/src/ifc/ifc_step_parser.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_step_parser.js +64 -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/ifc/ifc_stream_open.d.ts +131 -0
- package/compiled/src/ifc/ifc_stream_open.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_stream_open.js +116 -0
- package/compiled/src/ifc/ifc_stream_open.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_stream_open.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_stream_open.test.js +230 -0
- package/compiled/src/ifc/ifc_tile_extractor.d.ts +84 -0
- package/compiled/src/ifc/ifc_tile_extractor.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_tile_extractor.js +134 -0
- package/compiled/src/ifc/ifc_tile_extractor.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_tile_extractor.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_tile_extractor.test.js +118 -0
- package/compiled/src/ifc/ifc_typed_select_enum.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_typed_select_enum.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_typed_select_enum.test.js +60 -0
- package/compiled/src/index.d.ts +21 -1
- package/compiled/src/index.d.ts.map +1 -1
- package/compiled/src/index.js +28 -1
- package/compiled/src/logging/logger.d.ts +16 -2
- package/compiled/src/logging/logger.d.ts.map +1 -1
- package/compiled/src/logging/logger.js +34 -7
- package/compiled/src/logging/logger.test.js +30 -0
- package/compiled/src/mem/index.d.ts +17 -0
- package/compiled/src/mem/index.d.ts.map +1 -0
- package/compiled/src/mem/index.js +16 -0
- package/compiled/src/namespace_surface.test.d.ts +2 -0
- package/compiled/src/namespace_surface.test.d.ts.map +1 -0
- package/compiled/src/namespace_surface.test.js +43 -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/scripts/model_report_displacement.test.d.ts +2 -0
- package/compiled/src/scripts/model_report_displacement.test.d.ts.map +1 -0
- package/compiled/src/scripts/model_report_displacement.test.js +104 -0
- package/compiled/src/scripts/render_glb_paths.test.d.ts +2 -0
- package/compiled/src/scripts/render_glb_paths.test.d.ts.map +1 -0
- package/compiled/src/scripts/render_glb_paths.test.js +115 -0
- package/compiled/src/step/indexing/step_type_indexer.d.ts +20 -0
- package/compiled/src/step/indexing/step_type_indexer.d.ts.map +1 -1
- package/compiled/src/step/indexing/step_type_indexer.js +67 -0
- package/compiled/src/step/parsing/byte_source.d.ts +153 -0
- package/compiled/src/step/parsing/byte_source.d.ts.map +1 -0
- package/compiled/src/step/parsing/byte_source.js +106 -0
- package/compiled/src/step/parsing/byte_source.test.d.ts +2 -0
- package/compiled/src/step/parsing/byte_source.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/byte_source.test.js +47 -0
- package/compiled/src/step/parsing/byte_source_node.d.ts +41 -0
- package/compiled/src/step/parsing/byte_source_node.d.ts.map +1 -0
- package/compiled/src/step/parsing/byte_source_node.js +54 -0
- package/compiled/src/step/parsing/columnar_index.d.ts +103 -0
- package/compiled/src/step/parsing/columnar_index.d.ts.map +1 -0
- package/compiled/src/step/parsing/columnar_index.js +224 -0
- package/compiled/src/step/parsing/columnar_index.test.d.ts +2 -0
- package/compiled/src/step/parsing/columnar_index.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/columnar_index.test.js +155 -0
- package/compiled/src/step/parsing/cross_reference_registry.d.ts +95 -0
- package/compiled/src/step/parsing/cross_reference_registry.d.ts.map +1 -0
- package/compiled/src/step/parsing/cross_reference_registry.js +91 -0
- package/compiled/src/step/parsing/cross_reference_registry.test.d.ts +2 -0
- package/compiled/src/step/parsing/cross_reference_registry.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/cross_reference_registry.test.js +66 -0
- package/compiled/src/step/parsing/decode_utf8.d.ts +15 -0
- package/compiled/src/step/parsing/decode_utf8.d.ts.map +1 -1
- package/compiled/src/step/parsing/decode_utf8.js +28 -0
- package/compiled/src/step/parsing/express_ref_scan.d.ts +20 -0
- package/compiled/src/step/parsing/express_ref_scan.d.ts.map +1 -0
- package/compiled/src/step/parsing/express_ref_scan.js +91 -0
- package/compiled/src/step/parsing/express_ref_scan.test.d.ts +2 -0
- package/compiled/src/step/parsing/express_ref_scan.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/express_ref_scan.test.js +28 -0
- package/compiled/src/step/parsing/index_sidecar.d.ts +81 -0
- package/compiled/src/step/parsing/index_sidecar.d.ts.map +1 -0
- package/compiled/src/step/parsing/index_sidecar.js +283 -0
- package/compiled/src/step/parsing/index_sidecar.test.d.ts +2 -0
- package/compiled/src/step/parsing/index_sidecar.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/index_sidecar.test.js +122 -0
- package/compiled/src/step/parsing/inf_recovery_index.test.d.ts +2 -0
- package/compiled/src/step/parsing/inf_recovery_index.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/inf_recovery_index.test.js +108 -0
- package/compiled/src/step/parsing/prefix_type_index.d.ts +124 -0
- package/compiled/src/step/parsing/prefix_type_index.d.ts.map +1 -0
- package/compiled/src/step/parsing/prefix_type_index.js +207 -0
- package/compiled/src/step/parsing/prefix_type_index.test.d.ts +2 -0
- package/compiled/src/step/parsing/prefix_type_index.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/prefix_type_index.test.js +298 -0
- package/compiled/src/step/parsing/range_byte_source.d.ts +69 -0
- package/compiled/src/step/parsing/range_byte_source.d.ts.map +1 -0
- package/compiled/src/step/parsing/range_byte_source.js +78 -0
- package/compiled/src/step/parsing/range_byte_source.test.d.ts +2 -0
- package/compiled/src/step/parsing/range_byte_source.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/range_byte_source.test.js +70 -0
- package/compiled/src/step/parsing/record_event.d.ts +23 -0
- package/compiled/src/step/parsing/record_event.d.ts.map +1 -0
- package/compiled/src/step/parsing/record_event.js +1 -0
- package/compiled/src/step/parsing/record_field_cursor.d.ts +94 -0
- package/compiled/src/step/parsing/record_field_cursor.d.ts.map +1 -0
- package/compiled/src/step/parsing/record_field_cursor.js +189 -0
- package/compiled/src/step/parsing/step_deserialization_functions.d.ts +29 -0
- package/compiled/src/step/parsing/step_deserialization_functions.d.ts.map +1 -1
- package/compiled/src/step/parsing/step_deserialization_functions.js +45 -0
- package/compiled/src/step/parsing/step_deserialization_functions.test.js +59 -1
- package/compiled/src/step/parsing/step_parser.d.ts +66 -1
- package/compiled/src/step/parsing/step_parser.d.ts.map +1 -1
- package/compiled/src/step/parsing/step_parser.js +164 -10
- package/compiled/src/step/parsing/step_string_parser.js +8 -8
- package/compiled/src/step/parsing/streaming_index_builder.d.ts +141 -0
- package/compiled/src/step/parsing/streaming_index_builder.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_index_builder.js +280 -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_index_builder_async.test.d.ts +2 -0
- package/compiled/src/step/parsing/streaming_index_builder_async.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_index_builder_async.test.js +109 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts +71 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.js +88 -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/parsing/uint32_sink.d.ts +72 -0
- package/compiled/src/step/parsing/uint32_sink.d.ts.map +1 -0
- package/compiled/src/step/parsing/uint32_sink.js +180 -0
- package/compiled/src/step/parsing/uint32_sink.test.d.ts +2 -0
- package/compiled/src/step/parsing/uint32_sink.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/uint32_sink.test.js +199 -0
- package/compiled/src/step/step_buffer_provider.d.ts +48 -3
- package/compiled/src/step/step_buffer_provider.d.ts.map +1 -1
- package/compiled/src/step/step_buffer_provider.js +60 -11
- package/compiled/src/step/step_buffer_provider.test.js +14 -0
- package/compiled/src/step/step_entity_base.d.ts +65 -3
- package/compiled/src/step/step_entity_base.d.ts.map +1 -1
- package/compiled/src/step/step_entity_base.js +135 -3
- package/compiled/src/step/step_model_base.d.ts +221 -8
- package/compiled/src/step/step_model_base.d.ts.map +1 -1
- package/compiled/src/step/step_model_base.js +542 -7
- package/compiled/src/stream/index.d.ts +34 -0
- package/compiled/src/stream/index.d.ts.map +1 -0
- package/compiled/src/stream/index.js +32 -0
- package/compiled/src/version/version.js +1 -1
- package/compiled/tsconfig.tsbuildinfo +1 -1
- package/package.json +16 -1
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/** Type sentinel for "no concrete type" in the typeID column. */
|
|
2
|
+
export const COLUMN_UNDEFINED_TYPE = -1;
|
|
3
|
+
// Records per growth segment. 64 K rows × 16 B ≈ 1 MB per segment — growth
|
|
4
|
+
// never copies previously written rows, and finalize concatenates one column
|
|
5
|
+
// at a time so the transient overhead is one column's segments, not 2× the
|
|
6
|
+
// index.
|
|
7
|
+
// eslint-disable-next-line no-magic-numbers
|
|
8
|
+
const SEGMENT_ROWS = 64 * 1024;
|
|
9
|
+
/**
|
|
10
|
+
* A {@link StepIndexSink} that encodes top-level records straight into
|
|
11
|
+
* chunked-segment typed-array columns, so the parse holds **no per-record
|
|
12
|
+
* objects** for the (overwhelmingly common) simple records. Records with
|
|
13
|
+
* children keep their object form — inline entities are unfolded into the
|
|
14
|
+
* inline column range at {@link finalize}, and multi-mapping holders are
|
|
15
|
+
* retained for the model's `complexEntries`, matching the object path's
|
|
16
|
+
* behaviour entry-for-entry.
|
|
17
|
+
*
|
|
18
|
+
* `reset` supports the streaming builder's rare grow-and-restart: columns
|
|
19
|
+
* rewind to empty without reallocating the first segment.
|
|
20
|
+
*/
|
|
21
|
+
export class ColumnarIndexSink {
|
|
22
|
+
constructor() {
|
|
23
|
+
this.segments_ = [];
|
|
24
|
+
this.count_ = 0;
|
|
25
|
+
/** Entries with inlineEntities and/or multiMapping, keyed by localID. */
|
|
26
|
+
this.retained_ = new Map();
|
|
27
|
+
this.expressIdsSorted_ = true;
|
|
28
|
+
this.previousExpressID_ = 0;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* @return {number} Top-level records pushed so far.
|
|
32
|
+
*/
|
|
33
|
+
get topLevelCount() {
|
|
34
|
+
return this.count_;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Encode one completed top-level record into the columns. The entry object
|
|
38
|
+
* is not kept unless it carries children (inline entities / multi-mapping).
|
|
39
|
+
*
|
|
40
|
+
* @param entry The completed top-level index entry.
|
|
41
|
+
*/
|
|
42
|
+
pushTopLevel(entry) {
|
|
43
|
+
const localID = this.count_++;
|
|
44
|
+
const segmentIndex = Math.floor(localID / SEGMENT_ROWS);
|
|
45
|
+
const row = localID % SEGMENT_ROWS;
|
|
46
|
+
if (segmentIndex === this.segments_.length) {
|
|
47
|
+
this.segments_.push({
|
|
48
|
+
address: new Uint32Array(SEGMENT_ROWS),
|
|
49
|
+
length: new Uint32Array(SEGMENT_ROWS),
|
|
50
|
+
typeID: new Int32Array(SEGMENT_ROWS),
|
|
51
|
+
expressID: new Uint32Array(SEGMENT_ROWS),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
const segment = this.segments_[segmentIndex];
|
|
55
|
+
segment.address[row] = entry.address;
|
|
56
|
+
segment.length[row] = entry.length;
|
|
57
|
+
segment.typeID[row] =
|
|
58
|
+
entry.typeID === void 0 ? COLUMN_UNDEFINED_TYPE : entry.typeID;
|
|
59
|
+
segment.expressID[row] = entry.expressID;
|
|
60
|
+
if (entry.expressID < this.previousExpressID_) {
|
|
61
|
+
this.expressIdsSorted_ = false;
|
|
62
|
+
}
|
|
63
|
+
this.previousExpressID_ = entry.expressID;
|
|
64
|
+
if (entry.inlineEntities !== void 0 || entry.multiMapping !== void 0) {
|
|
65
|
+
this.retained_.set(localID, entry);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Rewind to empty (the streaming builder's grow-and-restart). The first
|
|
70
|
+
* segment is kept for reuse.
|
|
71
|
+
*/
|
|
72
|
+
reset() {
|
|
73
|
+
this.segments_.length = Math.min(this.segments_.length, 1);
|
|
74
|
+
this.count_ = 0;
|
|
75
|
+
this.retained_.clear();
|
|
76
|
+
this.expressIdsSorted_ = true;
|
|
77
|
+
this.previousExpressID_ = 0;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Snapshot the columns pushed SO FAR into a self-contained prefix index,
|
|
81
|
+
* without disturbing the sink — the parse can keep pushing afterwards and
|
|
82
|
+
* a later snapshot/finalize sees the full data. Safe to call between the
|
|
83
|
+
* cooperative parse's yields (the parser only suspends at top-level
|
|
84
|
+
* record boundaries, where the sink is consistent). Top-level localIDs
|
|
85
|
+
* are stable across snapshots (dense parse order), so consumers can carry
|
|
86
|
+
* per-localID cursors from one snapshot to the next; inline-range
|
|
87
|
+
* localIDs are NOT stable (the inline tail re-packs after the growing
|
|
88
|
+
* top-level range) and must not be carried across snapshots.
|
|
89
|
+
*
|
|
90
|
+
* @return {StepIndexColumns} A prefix columnar index over the records
|
|
91
|
+
* pushed so far.
|
|
92
|
+
*/
|
|
93
|
+
snapshot() {
|
|
94
|
+
return this.assemble_();
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Assemble the final columns: concatenate the top-level segments (one
|
|
98
|
+
* column at a time, bounding transient overhead to a single column's
|
|
99
|
+
* segments) and unfold retained inline entities into the inline range in
|
|
100
|
+
* the model's exact unfold order.
|
|
101
|
+
*
|
|
102
|
+
* @return {StepIndexColumns} The finished columnar index.
|
|
103
|
+
*/
|
|
104
|
+
finalize() {
|
|
105
|
+
return this.assemble_();
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Shared assembly behind {@link snapshot} and {@link finalize} — pure
|
|
109
|
+
* over the sink's current state.
|
|
110
|
+
*
|
|
111
|
+
* @return {StepIndexColumns} The assembled columnar index.
|
|
112
|
+
*/
|
|
113
|
+
assemble_() {
|
|
114
|
+
const topLevel = this.count_;
|
|
115
|
+
// Unfold inline entities exactly as StepModelBase does over the object
|
|
116
|
+
// array: scan in localID order appending children, then keep scanning
|
|
117
|
+
// the appended region (children of children follow all first-level
|
|
118
|
+
// children). Only retained entries can contribute — simple records have
|
|
119
|
+
// no children by construction.
|
|
120
|
+
const unfolded = [];
|
|
121
|
+
for (const entry of this.retained_.values()) {
|
|
122
|
+
if (entry.inlineEntities !== void 0) {
|
|
123
|
+
unfolded.push(...entry.inlineEntities);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
for (let where = 0; where < unfolded.length; ++where) {
|
|
127
|
+
const inlineEntities = unfolded[where].inlineEntities;
|
|
128
|
+
if (inlineEntities !== void 0) {
|
|
129
|
+
unfolded.push(...inlineEntities);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const count = topLevel + unfolded.length;
|
|
133
|
+
const address = concatColumn(this.segments_, 'address', topLevel, count);
|
|
134
|
+
const length = concatColumn(this.segments_, 'length', topLevel, count);
|
|
135
|
+
const typeID = new Int32Array(count);
|
|
136
|
+
for (let segment = 0; segment * SEGMENT_ROWS < topLevel; ++segment) {
|
|
137
|
+
const rows = Math.min(SEGMENT_ROWS, topLevel - segment * SEGMENT_ROWS);
|
|
138
|
+
typeID.set(this.segments_[segment].typeID.subarray(0, rows), segment * SEGMENT_ROWS);
|
|
139
|
+
}
|
|
140
|
+
const expressID = concatColumn(this.segments_, 'expressID', topLevel, topLevel);
|
|
141
|
+
for (let where = 0; where < unfolded.length; ++where) {
|
|
142
|
+
const entry = unfolded[where];
|
|
143
|
+
const row = topLevel + where;
|
|
144
|
+
address[row] = entry.address;
|
|
145
|
+
length[row] = entry.length;
|
|
146
|
+
typeID[row] =
|
|
147
|
+
entry.typeID === void 0 ? COLUMN_UNDEFINED_TYPE : entry.typeID;
|
|
148
|
+
}
|
|
149
|
+
let complexEntries;
|
|
150
|
+
for (const [localID, entry] of this.retained_) {
|
|
151
|
+
if (entry.multiMapping !== void 0) {
|
|
152
|
+
(complexEntries ??= new Map()).set(localID, cloneIndexEntry(entry));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
address,
|
|
157
|
+
length,
|
|
158
|
+
typeID,
|
|
159
|
+
expressID,
|
|
160
|
+
count,
|
|
161
|
+
firstInlineElement: topLevel,
|
|
162
|
+
complexEntries,
|
|
163
|
+
expressIdsSorted: this.expressIdsSorted_,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Clone an index entry (and its multiMapping sub-entries, which models
|
|
169
|
+
* also stamp) down to the persistent index fields.
|
|
170
|
+
*
|
|
171
|
+
* Models materialise complex entries by writing lazy parse state —
|
|
172
|
+
* vtable views, buffer references, entity instances — onto the entry
|
|
173
|
+
* objects IN PLACE (see StepModelBase.invalidate, which clears exactly
|
|
174
|
+
* those fields). Handing every snapshot/finalize the same retained
|
|
175
|
+
* object therefore let one model poison every other model built over
|
|
176
|
+
* the same sink: a throwaway prefix model (parse-time preview channel)
|
|
177
|
+
* stamped its own vtable views, and the durable model's short-circuit
|
|
178
|
+
* (`vtableIndex !== undefined`) then read stale views — "Value in STEP
|
|
179
|
+
* was incorrectly typed" on AP214's complex-instance transforms.
|
|
180
|
+
* Cloning per assembly keeps each model's lazy state private.
|
|
181
|
+
* `inlineEntities` stays shared: inline records are unfolded into
|
|
182
|
+
* column scalars above and their objects are never stamped.
|
|
183
|
+
*
|
|
184
|
+
* @param entry The retained entry to clone.
|
|
185
|
+
* @return {StepIndexEntryBase} A fresh holder with persistent fields only.
|
|
186
|
+
*/
|
|
187
|
+
function cloneIndexEntry(entry) {
|
|
188
|
+
const clone = {
|
|
189
|
+
address: entry.address,
|
|
190
|
+
length: entry.length,
|
|
191
|
+
};
|
|
192
|
+
if (entry.typeID !== void 0) {
|
|
193
|
+
clone.typeID = entry.typeID;
|
|
194
|
+
}
|
|
195
|
+
if (entry.expressID !== void 0) {
|
|
196
|
+
clone.expressID = entry.expressID;
|
|
197
|
+
}
|
|
198
|
+
if (entry.inlineEntities !== void 0) {
|
|
199
|
+
clone.inlineEntities = entry.inlineEntities;
|
|
200
|
+
}
|
|
201
|
+
if (entry.multiMapping !== void 0) {
|
|
202
|
+
clone.multiMapping = entry.multiMapping.map(cloneIndexEntry);
|
|
203
|
+
}
|
|
204
|
+
return clone;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Concatenate one Uint32 column's segments into a final array of
|
|
208
|
+
* `finalLength`, copying `rows` valid rows.
|
|
209
|
+
*
|
|
210
|
+
* @param segments The growth segments.
|
|
211
|
+
* @param column Which column to concatenate.
|
|
212
|
+
* @param rows Valid rows across the segments.
|
|
213
|
+
* @param finalLength Length of the final array (≥ rows; the tail is for
|
|
214
|
+
* inline rows filled by the caller).
|
|
215
|
+
* @return {Uint32Array} The concatenated column.
|
|
216
|
+
*/
|
|
217
|
+
function concatColumn(segments, column, rows, finalLength) {
|
|
218
|
+
const result = new Uint32Array(finalLength);
|
|
219
|
+
for (let segment = 0; segment * SEGMENT_ROWS < rows; ++segment) {
|
|
220
|
+
const valid = Math.min(SEGMENT_ROWS, rows - segment * SEGMENT_ROWS);
|
|
221
|
+
result.set(segments[segment][column].subarray(0, valid), segment * SEGMENT_ROWS);
|
|
222
|
+
}
|
|
223
|
+
return result;
|
|
224
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"columnar_index.test.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/columnar_index.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/* eslint-disable no-magic-numbers, @typescript-eslint/no-explicit-any */
|
|
2
|
+
// M7: the columnar (no-object-phase) index build must produce a model
|
|
3
|
+
// indistinguishable from the object-path build — identical SoA columns,
|
|
4
|
+
// identical lookup behaviour, identical type index — including on AP214
|
|
5
|
+
// fixtures with inline entities and multi-mappings, the paths the object
|
|
6
|
+
// walk handles specially.
|
|
7
|
+
import * as fs from "fs";
|
|
8
|
+
import { describe, expect, test } from "@jest/globals";
|
|
9
|
+
import ParsingBuffer from "../../parsing/parsing_buffer.js";
|
|
10
|
+
import IfcStepParser from "../../ifc/ifc_step_parser.js";
|
|
11
|
+
import IfcStepModel from "../../ifc/ifc_step_model.js";
|
|
12
|
+
import AP214StepParser from "../../AP214E3_2010/ap214_step_parser.js";
|
|
13
|
+
import AP214StepModel from "../../AP214E3_2010/ap214_step_model.js";
|
|
14
|
+
import { BufferByteSource } from "./byte_source.js";
|
|
15
|
+
import { buildColumnarIndexStreaming } from "./streaming_index_builder.js";
|
|
16
|
+
import { ColumnarIndexSink } from "./columnar_index.js";
|
|
17
|
+
import { ParseResult } from "./step_parser.js";
|
|
18
|
+
import { IfcProduct, IfcRoot } from "../../ifc/ifc4_gen/index.js";
|
|
19
|
+
/**
|
|
20
|
+
* Parse a file resident via the object path and return buffer + elements.
|
|
21
|
+
*
|
|
22
|
+
* @param path The file to parse.
|
|
23
|
+
* @param parser The parser instance for its schema.
|
|
24
|
+
* @return {object} `{ bytes, elements }`.
|
|
25
|
+
*/
|
|
26
|
+
function objectParse(path, parser) {
|
|
27
|
+
const bytes = new Uint8Array(fs.readFileSync(path));
|
|
28
|
+
const input = new ParsingBuffer(bytes);
|
|
29
|
+
parser.parseHeader(input);
|
|
30
|
+
const [index, result] = parser.parseDataBlock(input);
|
|
31
|
+
expect(result).toBe(ParseResult.COMPLETE);
|
|
32
|
+
return { bytes, elements: index.elements };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Assert two models have byte-identical internal columns and equal type
|
|
36
|
+
* indexes across every type either contains.
|
|
37
|
+
*
|
|
38
|
+
* @param a First model.
|
|
39
|
+
* @param b Second model.
|
|
40
|
+
*/
|
|
41
|
+
function expectModelParity(a, b) {
|
|
42
|
+
expect(a.count_).toBe(b.count_);
|
|
43
|
+
expect(a.firstInlineElement_).toBe(b.firstInlineElement_);
|
|
44
|
+
expect(Array.from(a.address_)).toEqual(Array.from(b.address_));
|
|
45
|
+
expect(Array.from(a.length_)).toEqual(Array.from(b.length_));
|
|
46
|
+
expect(Array.from(a.typeID_)).toEqual(Array.from(b.typeID_));
|
|
47
|
+
expect(Array.from(a.expressID_)).toEqual(Array.from(b.expressID_));
|
|
48
|
+
const typesA = new Set(a.typeIndex.types());
|
|
49
|
+
const typesB = new Set(b.typeIndex.types());
|
|
50
|
+
expect(typesA).toEqual(typesB);
|
|
51
|
+
for (const type of typesA) {
|
|
52
|
+
expect(b.typeIndex.count(type)).toBe(a.typeIndex.count(type));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
describe("columnar index build (M7)", () => {
|
|
56
|
+
test("IFC: columnar streamed model matches the object-path model", () => {
|
|
57
|
+
const path = "data/index.ifc";
|
|
58
|
+
const { bytes, elements } = objectParse(path, IfcStepParser.Instance);
|
|
59
|
+
const objectModel = new IfcStepModel(bytes, elements);
|
|
60
|
+
const { columns, result } = buildColumnarIndexStreaming(new BufferByteSource(bytes), IfcStepParser.Instance, 4 * 1024);
|
|
61
|
+
expect(result).toBe(ParseResult.COMPLETE);
|
|
62
|
+
const columnarModel = new IfcStepModel(bytes, columns);
|
|
63
|
+
expectModelParity(objectModel, columnarModel);
|
|
64
|
+
// Behavioural spot checks through the public surface.
|
|
65
|
+
const roots = new Set(objectModel.expressIDsOfTypes(IfcRoot));
|
|
66
|
+
expect(new Set(columnarModel.expressIDsOfTypes(IfcRoot))).toEqual(roots);
|
|
67
|
+
expect(new Set(columnarModel.expressIDsOfTypes(IfcProduct)))
|
|
68
|
+
.toEqual(new Set(objectModel.expressIDsOfTypes(IfcProduct)));
|
|
69
|
+
for (const expressID of roots) {
|
|
70
|
+
expect(columnarModel.getElementByExpressID(expressID)?.expressID)
|
|
71
|
+
.toBe(objectModel.getElementByExpressID(expressID)?.expressID);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
test.each([
|
|
75
|
+
["as1-oc-214.stp"],
|
|
76
|
+
["ap214-mapped-item-test.step"],
|
|
77
|
+
["ap214-multibody-part.step"],
|
|
78
|
+
])("AP214 (inline/multi-mapping): parity on %s", (name) => {
|
|
79
|
+
const path = `data/${name}`;
|
|
80
|
+
const { bytes, elements } = objectParse(path, AP214StepParser.Instance);
|
|
81
|
+
const objectModel = new AP214StepModel(bytes, elements);
|
|
82
|
+
const { columns, result } = buildColumnarIndexStreaming(new BufferByteSource(bytes), AP214StepParser.Instance, 4 * 1024);
|
|
83
|
+
expect(result).toBe(ParseResult.COMPLETE);
|
|
84
|
+
const columnarModel = new AP214StepModel(bytes, columns);
|
|
85
|
+
// Inline entities must actually be present for these fixtures to prove
|
|
86
|
+
// the unfold path (guard against a silently trivial test).
|
|
87
|
+
if (name !== "as1-oc-214.stp") {
|
|
88
|
+
expect(columnarModel.count_).toBeGreaterThan(columnarModel.firstInlineElement_);
|
|
89
|
+
}
|
|
90
|
+
expectModelParity(objectModel, columnarModel);
|
|
91
|
+
});
|
|
92
|
+
test("the sink drops simple records but retains complex ones", () => {
|
|
93
|
+
const sink = new ColumnarIndexSink();
|
|
94
|
+
sink.pushTopLevel({ address: 0, length: 10, typeID: 5, expressID: 1 });
|
|
95
|
+
sink.pushTopLevel({
|
|
96
|
+
address: 10,
|
|
97
|
+
length: 20,
|
|
98
|
+
typeID: 0,
|
|
99
|
+
expressID: 2,
|
|
100
|
+
multiMapping: [{ address: 12, length: 5, typeID: 7 }],
|
|
101
|
+
});
|
|
102
|
+
const columns = sink.finalize();
|
|
103
|
+
expect(columns.firstInlineElement).toBe(2);
|
|
104
|
+
expect(columns.count).toBe(2);
|
|
105
|
+
expect(columns.complexEntries?.size).toBe(1);
|
|
106
|
+
expect(columns.complexEntries?.get(1)?.multiMapping?.[0].typeID).toBe(7);
|
|
107
|
+
expect(Array.from(columns.typeID)).toEqual([5, 0]);
|
|
108
|
+
});
|
|
109
|
+
test("inline entities unfold in the model object-walk order", () => {
|
|
110
|
+
const sink = new ColumnarIndexSink();
|
|
111
|
+
// Two parents with children; first parent's child itself has a child.
|
|
112
|
+
// Object-path order: parents (0,1), then first-level children in parent
|
|
113
|
+
// order (2 = p0c, 3 = p1c), then second-level (4 = p0c's child).
|
|
114
|
+
sink.pushTopLevel({
|
|
115
|
+
address: 0,
|
|
116
|
+
length: 10,
|
|
117
|
+
typeID: 1,
|
|
118
|
+
expressID: 1,
|
|
119
|
+
inlineEntities: [{
|
|
120
|
+
address: 2,
|
|
121
|
+
length: 3,
|
|
122
|
+
typeID: 10,
|
|
123
|
+
inlineEntities: [{ address: 3, length: 1, typeID: 20 }],
|
|
124
|
+
}],
|
|
125
|
+
});
|
|
126
|
+
sink.pushTopLevel({
|
|
127
|
+
address: 10,
|
|
128
|
+
length: 10,
|
|
129
|
+
typeID: 2,
|
|
130
|
+
expressID: 2,
|
|
131
|
+
inlineEntities: [{ address: 12, length: 3, typeID: 11 }],
|
|
132
|
+
});
|
|
133
|
+
const columns = sink.finalize();
|
|
134
|
+
expect(columns.firstInlineElement).toBe(2);
|
|
135
|
+
expect(columns.count).toBe(5);
|
|
136
|
+
expect(Array.from(columns.typeID)).toEqual([1, 2, 10, 11, 20]);
|
|
137
|
+
expect(Array.from(columns.address)).toEqual([0, 10, 2, 12, 3]);
|
|
138
|
+
});
|
|
139
|
+
test("reset rewinds for the grow-and-restart", () => {
|
|
140
|
+
const sink = new ColumnarIndexSink();
|
|
141
|
+
sink.pushTopLevel({ address: 0, length: 1, typeID: 1, expressID: 9 });
|
|
142
|
+
sink.reset();
|
|
143
|
+
sink.pushTopLevel({ address: 5, length: 2, typeID: 3, expressID: 1 });
|
|
144
|
+
const columns = sink.finalize();
|
|
145
|
+
expect(columns.count).toBe(1);
|
|
146
|
+
expect(Array.from(columns.address)).toEqual([5]);
|
|
147
|
+
expect(columns.expressIdsSorted).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
test("detects unsorted express IDs", () => {
|
|
150
|
+
const sink = new ColumnarIndexSink();
|
|
151
|
+
sink.pushTopLevel({ address: 0, length: 1, typeID: 1, expressID: 10 });
|
|
152
|
+
sink.pushTopLevel({ address: 1, length: 1, typeID: 1, expressID: 5 });
|
|
153
|
+
expect(sink.finalize().expressIdsSorted).toBe(false);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { EntityAddress } from "../../core/model_uri.js";
|
|
2
|
+
import { RecordHandler } from "./streaming_record_dispatcher.js";
|
|
3
|
+
/**
|
|
4
|
+
* Reads the `Location` string of a cross-reference entity by express ID.
|
|
5
|
+
* Implemented over the finished (or partially materialised) model — a thin
|
|
6
|
+
* seam so the registry's link resolution is testable without a full model.
|
|
7
|
+
* `IfcExternalReference.Location` is the canonical field; STEP AP242's external
|
|
8
|
+
* references expose their location the same way.
|
|
9
|
+
*/
|
|
10
|
+
export interface ReferenceLocationReader {
|
|
11
|
+
/**
|
|
12
|
+
* @param expressID The cross-reference entity's express ID.
|
|
13
|
+
* @return {string | null | undefined} Its `Location`, or null/undefined when
|
|
14
|
+
* absent.
|
|
15
|
+
*/
|
|
16
|
+
locationOf(expressID: number): string | null | undefined;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* An outbound federation link discovered from a cross-reference: the
|
|
20
|
+
* referencing entity in this model, the raw location it declared, and — once
|
|
21
|
+
* resolved against the model's own URI — the absolute URI (and, if the
|
|
22
|
+
* location carried a `#expressID` fragment, the entity address) it points at.
|
|
23
|
+
*/
|
|
24
|
+
export interface CrossReferenceLink {
|
|
25
|
+
/** Express ID of the referencing entity in the source model. */
|
|
26
|
+
fromExpressID: number;
|
|
27
|
+
/** The raw `Location` string as authored in the file. */
|
|
28
|
+
location: string;
|
|
29
|
+
/** The location resolved to an absolute URI against the source model URI. */
|
|
30
|
+
targetURI: string;
|
|
31
|
+
/** The target entity address, when the location carried a `#expressID`. */
|
|
32
|
+
targetEntity?: EntityAddress;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Collects a model's **outbound cross-model references** during the streaming
|
|
36
|
+
* parse and, once locations are readable, resolves them into navigable
|
|
37
|
+
* federation links (M5 / design S3).
|
|
38
|
+
*
|
|
39
|
+
* The links come from IFC's own reference entities — `IfcExternalReference`
|
|
40
|
+
* and its subtypes (`IfcDocumentReference`, `IfcClassificationReference`,
|
|
41
|
+
* `IfcLibraryReference`) — and, for STEP AP242, its external references. Two
|
|
42
|
+
* phases, matching M2's "identify while parsing, resolve on demand":
|
|
43
|
+
*
|
|
44
|
+
* 1. **Identify** — subscribe {@link handler} to a
|
|
45
|
+
* {@link StreamingRecordDispatcher} for the reference types
|
|
46
|
+
* (`dispatcher.on([IfcExternalReference], reg.handler)`); it records the
|
|
47
|
+
* express ID of every such record as it streams past. Cheap and idempotent
|
|
48
|
+
* (a `Set`), so the rare grow-restart is harmless.
|
|
49
|
+
* 2. **Resolve** — after parse, {@link resolve} reads each reference's
|
|
50
|
+
* `Location` via a {@link ReferenceLocationReader} and resolves it against
|
|
51
|
+
* the source model URI, yielding {@link CrossReferenceLink}s the UI renders
|
|
52
|
+
* as links. Visiting one opens the target model in the `ModelRegistry`.
|
|
53
|
+
*
|
|
54
|
+
* The location read is deferred because the event stream carries only
|
|
55
|
+
* `(localID, expressID, typeID)` — not attribute strings; pulling `Location`
|
|
56
|
+
* needs the entity's fields, which is a model read, not a parse event.
|
|
57
|
+
*/
|
|
58
|
+
export declare class CrossReferenceRegistry<TypeIDType extends number> {
|
|
59
|
+
private readonly sourceURI_;
|
|
60
|
+
private readonly fromExpressIDs_;
|
|
61
|
+
/**
|
|
62
|
+
* @param sourceURI_ The URI of the model these references were found in —
|
|
63
|
+
* the base for resolving relative locations.
|
|
64
|
+
*/
|
|
65
|
+
constructor(sourceURI_: string);
|
|
66
|
+
/**
|
|
67
|
+
* Record one cross-reference entity. Bind to a dispatcher subscription
|
|
68
|
+
* filtered to the reference types; every record it is handed is taken to be
|
|
69
|
+
* a cross-reference (the dispatcher does the type filtering).
|
|
70
|
+
*
|
|
71
|
+
* @param localID Unused (kept for the RecordHandler shape).
|
|
72
|
+
* @param expressID The reference entity's express ID.
|
|
73
|
+
* @param typeID Unused (the dispatcher already matched the type set).
|
|
74
|
+
*/
|
|
75
|
+
readonly handler: RecordHandler<TypeIDType>;
|
|
76
|
+
/**
|
|
77
|
+
* @return {number} The number of cross-references collected.
|
|
78
|
+
*/
|
|
79
|
+
get count(): number;
|
|
80
|
+
/**
|
|
81
|
+
* @return {IterableIterator<number>} The express IDs of the collected
|
|
82
|
+
* reference entities.
|
|
83
|
+
*/
|
|
84
|
+
expressIDs(): IterableIterator<number>;
|
|
85
|
+
/**
|
|
86
|
+
* Resolve the collected references into navigable links by reading each
|
|
87
|
+
* one's `Location` and resolving it against the source model URI. References
|
|
88
|
+
* whose location is absent (null / empty) are skipped — they carry no link.
|
|
89
|
+
*
|
|
90
|
+
* @param reader Reads the `Location` of an express ID.
|
|
91
|
+
* @return {CrossReferenceLink[]} The resolved outbound links.
|
|
92
|
+
*/
|
|
93
|
+
resolve(reader: ReferenceLocationReader): CrossReferenceLink[];
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=cross_reference_registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross_reference_registry.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/cross_reference_registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAoB,MAAM,sBAAsB,CAAA;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAG7D;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IAEtC;;;;OAIG;IACH,UAAU,CAAE,SAAS,EAAE,MAAM,GAAI,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAC3D;AAGD;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IAEjC,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAA;IAErB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAA;IAEhB,6EAA6E;IAC7E,SAAS,EAAE,MAAM,CAAA;IAEjB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,aAAa,CAAA;CAC7B;AAOD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,sBAAsB,CAAC,UAAU,SAAS,MAAM;IAQ9C,OAAO,CAAC,QAAQ,CAAC,UAAU;IANxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoB;IAEpD;;;OAGG;gBAC2B,UAAU,EAAE,MAAM;IAEhD;;;;;;;;OAQG;IACH,SAAgB,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,CAG/C;IAEH;;OAEG;IACH,IAAW,KAAK,IAAI,MAAM,CAEzB;IAED;;;OAGG;IACI,UAAU,IAAI,gBAAgB,CAAC,MAAM,CAAC;IAI7C;;;;;;;OAOG;IACI,OAAO,CAAE,MAAM,EAAE,uBAAuB,GAAI,kBAAkB,EAAE;CA8BxE"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { resolveReference } from "../../core/model_uri.js";
|
|
2
|
+
const FRAGMENT = "#";
|
|
3
|
+
const RADIX = 10;
|
|
4
|
+
/**
|
|
5
|
+
* Collects a model's **outbound cross-model references** during the streaming
|
|
6
|
+
* parse and, once locations are readable, resolves them into navigable
|
|
7
|
+
* federation links (M5 / design S3).
|
|
8
|
+
*
|
|
9
|
+
* The links come from IFC's own reference entities — `IfcExternalReference`
|
|
10
|
+
* and its subtypes (`IfcDocumentReference`, `IfcClassificationReference`,
|
|
11
|
+
* `IfcLibraryReference`) — and, for STEP AP242, its external references. Two
|
|
12
|
+
* phases, matching M2's "identify while parsing, resolve on demand":
|
|
13
|
+
*
|
|
14
|
+
* 1. **Identify** — subscribe {@link handler} to a
|
|
15
|
+
* {@link StreamingRecordDispatcher} for the reference types
|
|
16
|
+
* (`dispatcher.on([IfcExternalReference], reg.handler)`); it records the
|
|
17
|
+
* express ID of every such record as it streams past. Cheap and idempotent
|
|
18
|
+
* (a `Set`), so the rare grow-restart is harmless.
|
|
19
|
+
* 2. **Resolve** — after parse, {@link resolve} reads each reference's
|
|
20
|
+
* `Location` via a {@link ReferenceLocationReader} and resolves it against
|
|
21
|
+
* the source model URI, yielding {@link CrossReferenceLink}s the UI renders
|
|
22
|
+
* as links. Visiting one opens the target model in the `ModelRegistry`.
|
|
23
|
+
*
|
|
24
|
+
* The location read is deferred because the event stream carries only
|
|
25
|
+
* `(localID, expressID, typeID)` — not attribute strings; pulling `Location`
|
|
26
|
+
* needs the entity's fields, which is a model read, not a parse event.
|
|
27
|
+
*/
|
|
28
|
+
export class CrossReferenceRegistry {
|
|
29
|
+
/**
|
|
30
|
+
* @param sourceURI_ The URI of the model these references were found in —
|
|
31
|
+
* the base for resolving relative locations.
|
|
32
|
+
*/
|
|
33
|
+
constructor(sourceURI_) {
|
|
34
|
+
this.sourceURI_ = sourceURI_;
|
|
35
|
+
this.fromExpressIDs_ = new Set();
|
|
36
|
+
/**
|
|
37
|
+
* Record one cross-reference entity. Bind to a dispatcher subscription
|
|
38
|
+
* filtered to the reference types; every record it is handed is taken to be
|
|
39
|
+
* a cross-reference (the dispatcher does the type filtering).
|
|
40
|
+
*
|
|
41
|
+
* @param localID Unused (kept for the RecordHandler shape).
|
|
42
|
+
* @param expressID The reference entity's express ID.
|
|
43
|
+
* @param typeID Unused (the dispatcher already matched the type set).
|
|
44
|
+
*/
|
|
45
|
+
this.handler = (localID, expressID, typeID) => {
|
|
46
|
+
this.fromExpressIDs_.add(expressID);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* @return {number} The number of cross-references collected.
|
|
51
|
+
*/
|
|
52
|
+
get count() {
|
|
53
|
+
return this.fromExpressIDs_.size;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* @return {IterableIterator<number>} The express IDs of the collected
|
|
57
|
+
* reference entities.
|
|
58
|
+
*/
|
|
59
|
+
expressIDs() {
|
|
60
|
+
return this.fromExpressIDs_.keys();
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Resolve the collected references into navigable links by reading each
|
|
64
|
+
* one's `Location` and resolving it against the source model URI. References
|
|
65
|
+
* whose location is absent (null / empty) are skipped — they carry no link.
|
|
66
|
+
*
|
|
67
|
+
* @param reader Reads the `Location` of an express ID.
|
|
68
|
+
* @return {CrossReferenceLink[]} The resolved outbound links.
|
|
69
|
+
*/
|
|
70
|
+
resolve(reader) {
|
|
71
|
+
const links = [];
|
|
72
|
+
for (const fromExpressID of this.fromExpressIDs_) {
|
|
73
|
+
const location = reader.locationOf(fromExpressID);
|
|
74
|
+
if (location === null || location === void 0 || location.length === 0) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const resolved = resolveReference(this.sourceURI_, location);
|
|
78
|
+
const link = { fromExpressID, location, targetURI: resolved };
|
|
79
|
+
// A location may itself address a specific entity (model.ifc#42).
|
|
80
|
+
const hash = resolved.lastIndexOf(FRAGMENT);
|
|
81
|
+
if (hash >= 0 && /^\d+$/.test(resolved.slice(hash + 1))) {
|
|
82
|
+
link.targetEntity = {
|
|
83
|
+
modelURI: resolved.slice(0, hash),
|
|
84
|
+
expressID: parseInt(resolved.slice(hash + 1), RADIX),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
links.push(link);
|
|
88
|
+
}
|
|
89
|
+
return links;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross_reference_registry.test.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/cross_reference_registry.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/* eslint-disable no-magic-numbers */
|
|
2
|
+
// M5: outbound cross-model references are collected during the parse (by type,
|
|
3
|
+
// via the dispatcher) and resolved to navigable federation links against the
|
|
4
|
+
// source model URI once their Location strings are readable.
|
|
5
|
+
import { describe, expect, test } from "@jest/globals";
|
|
6
|
+
import { CrossReferenceRegistry, } from "./cross_reference_registry.js";
|
|
7
|
+
import { StreamingRecordDispatcher } from "./streaming_record_dispatcher.js";
|
|
8
|
+
import { IfcExternalReference } from "../../ifc/ifc4_gen/index.js";
|
|
9
|
+
/**
|
|
10
|
+
* A mock reader over a fixed express-ID → Location map.
|
|
11
|
+
*
|
|
12
|
+
* @param locations The express-ID → Location map.
|
|
13
|
+
* @return {ReferenceLocationReader} The reader.
|
|
14
|
+
*/
|
|
15
|
+
function reader(locations) {
|
|
16
|
+
return { locationOf: (expressID) => locations[expressID] };
|
|
17
|
+
}
|
|
18
|
+
describe("CrossReferenceRegistry", () => {
|
|
19
|
+
test("collects references handed to its handler and resolves them", () => {
|
|
20
|
+
const registry = new CrossReferenceRegistry("https://ex.com/site/plan.ifc");
|
|
21
|
+
// Simulate the dispatcher delivering three reference records.
|
|
22
|
+
registry.handler(0, 100, 1);
|
|
23
|
+
registry.handler(1, 200, 1);
|
|
24
|
+
registry.handler(2, 300, 1);
|
|
25
|
+
expect(registry.count).toBe(3);
|
|
26
|
+
const links = registry.resolve(reader({
|
|
27
|
+
100: "../shared/grid.ifc",
|
|
28
|
+
200: "https://other.org/lib.ifc",
|
|
29
|
+
300: "wing-A.ifc#4022",
|
|
30
|
+
}));
|
|
31
|
+
const byFrom = new Map(links.map((l) => [l.fromExpressID, l]));
|
|
32
|
+
expect(byFrom.get(100)?.targetURI).toBe("https://ex.com/shared/grid.ifc");
|
|
33
|
+
expect(byFrom.get(200)?.targetURI).toBe("https://other.org/lib.ifc");
|
|
34
|
+
// A location with a #expressID resolves to a full entity address.
|
|
35
|
+
const wing = byFrom.get(300);
|
|
36
|
+
expect(wing?.targetURI).toBe("https://ex.com/site/wing-A.ifc#4022");
|
|
37
|
+
expect(wing?.targetEntity).toEqual({
|
|
38
|
+
modelURI: "https://ex.com/site/wing-A.ifc",
|
|
39
|
+
expressID: 4022,
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
test("skips references with no location", () => {
|
|
43
|
+
const registry = new CrossReferenceRegistry("base.ifc");
|
|
44
|
+
registry.handler(0, 1, 1);
|
|
45
|
+
registry.handler(1, 2, 1);
|
|
46
|
+
const links = registry.resolve(reader({ 1: null, 2: "" }));
|
|
47
|
+
expect(links).toEqual([]);
|
|
48
|
+
});
|
|
49
|
+
test("is idempotent under the streaming grow-restart (dedupes express IDs)", () => {
|
|
50
|
+
const registry = new CrossReferenceRegistry("base.ifc");
|
|
51
|
+
registry.handler(0, 42, 1);
|
|
52
|
+
registry.handler(0, 42, 1); // re-fire from localID 0 after a restart
|
|
53
|
+
expect(registry.count).toBe(1);
|
|
54
|
+
});
|
|
55
|
+
test("wires to the dispatcher, collecting only the reference types", () => {
|
|
56
|
+
const registry = new CrossReferenceRegistry("base.ifc");
|
|
57
|
+
const dispatcher = new StreamingRecordDispatcher();
|
|
58
|
+
dispatcher.on([IfcExternalReference], registry.handler);
|
|
59
|
+
// One record of a matching (subtype-closure) type, one outside it.
|
|
60
|
+
const matching = IfcExternalReference.query[0];
|
|
61
|
+
const nonMatching = 10000000; // not in the reference closure
|
|
62
|
+
dispatcher.onRecordIndexed(0, 500, matching);
|
|
63
|
+
dispatcher.onRecordIndexed(1, 600, nonMatching);
|
|
64
|
+
expect([...registry.expressIDs()]).toEqual([500]);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -27,6 +27,21 @@
|
|
|
27
27
|
* @return The decoded string.
|
|
28
28
|
*/
|
|
29
29
|
export declare function decodeUtf8(view: Uint8Array): string;
|
|
30
|
+
/**
|
|
31
|
+
* Decode the raw byte run of a STEP string literal.
|
|
32
|
+
*
|
|
33
|
+
* ISO 10303-21 says raw (non-\X\-escaped) bytes are ISO 8859-1, but modern
|
|
34
|
+
* exporters routinely write UTF-8 (and some, like Onshape's ST-Developer,
|
|
35
|
+
* write outright invalid sequences). The lenient default decoder mapped every
|
|
36
|
+
* non-UTF-8 byte to U+FFFD, so a spec-conformant latin-1 'Küche' surfaced as
|
|
37
|
+
* 'K�che' in product names and titles. Decode as strict UTF-8 first (the
|
|
38
|
+
* common modern case, and unambiguous when it validates), and fall back to
|
|
39
|
+
* exact ISO 8859-1 (byte = code point, which cannot fail) when it doesn't.
|
|
40
|
+
*
|
|
41
|
+
* @param view The bytes of the string literal's raw run.
|
|
42
|
+
* @return The decoded string.
|
|
43
|
+
*/
|
|
44
|
+
export declare function decodeStepString(view: Uint8Array): string;
|
|
30
45
|
/**
|
|
31
46
|
* Install a global, idempotent `TextDecoder.prototype.decode` shim that copies a
|
|
32
47
|
* view out of a resizable/growable buffer before decoding. This covers decodes
|