ifc_lite_wasm/api/
parsing.rs1use super::IfcAPI;
8use ifc_lite_core::EntityScanner;
9use wasm_bindgen::prelude::*;
10
11#[wasm_bindgen]
12impl IfcAPI {
13 #[wasm_bindgen(js_name = scanEntitiesFast)]
17 pub fn scan_entities_fast(&self, content: &str) -> JsValue {
18 Self::scan_entities_fast_inner(content.as_bytes())
19 }
20
21 #[wasm_bindgen(js_name = scanEntitiesFastBytes)]
25 pub fn scan_entities_fast_bytes(&self, data: &[u8]) -> JsValue {
26 Self::scan_entities_fast_inner(data)
27 }
28
29 fn scan_entities_fast_inner(content: &[u8]) -> JsValue {
30 use serde::{Deserialize, Serialize};
31 use serde_wasm_bindgen::to_value;
32
33 #[derive(Serialize, Deserialize)]
34 #[serde(rename_all = "camelCase")]
35 struct EntityRefJs {
36 express_id: u32,
37 #[serde(rename = "type")]
38 entity_type: String,
39 byte_offset: usize,
40 byte_length: usize,
41 line_number: usize,
42 }
43
44 let mut scanner = EntityScanner::new(content);
45 let mut refs = Vec::new();
46 let bytes = content;
47
48 let mut last_position = 0;
50 let mut line_count = 1; let mut type_cache: rustc_hash::FxHashMap<&str, String> = rustc_hash::FxHashMap::default();
54
55 while let Some((id, type_name, start, end)) = scanner.next_entity() {
56 if start > last_position {
58 line_count += bytes[last_position..start]
59 .iter()
60 .filter(|&&b| b == b'\n')
61 .count();
62 }
63
64 let entity_type = type_cache
65 .entry(type_name)
66 .or_insert_with(|| type_name.to_string())
67 .clone();
68
69 refs.push(EntityRefJs {
70 express_id: id,
71 entity_type,
72 byte_offset: start,
73 byte_length: end - start,
74 line_number: line_count,
75 });
76
77 last_position = end;
78 }
79
80 to_value(&refs).unwrap_or_else(|_| js_sys::Array::new().into())
81 }
82
83 #[wasm_bindgen(js_name = scanGeometryEntitiesFast)]
88 pub fn scan_geometry_entities_fast(&self, content: &str) -> JsValue {
89 use serde::{Deserialize, Serialize};
90 use serde_wasm_bindgen::to_value;
91
92 #[derive(Serialize, Deserialize)]
93 #[serde(rename_all = "camelCase")]
94 struct GeometryEntityRefJs {
95 express_id: u32,
96 #[serde(rename = "type")]
97 entity_type: String,
98 byte_offset: usize,
99 byte_length: usize,
100 }
101
102 let mut scanner = EntityScanner::new(content.as_bytes());
103 let mut refs = Vec::new();
104
105 while let Some((id, type_name, start, end)) = scanner.next_entity() {
107 if ifc_lite_core::has_geometry_by_name(type_name) {
109 refs.push(GeometryEntityRefJs {
110 express_id: id,
111 entity_type: type_name.to_string(),
112 byte_offset: start,
113 byte_length: end - start,
114 });
115 }
116 }
117
118 to_value(&refs).unwrap_or_else(|_| js_sys::Array::new().into())
119 }
120
121}