ifc_lite_wasm/api/
scan_proposals.rs1use super::IfcAPI;
5use ifc_lite_processing::scan_proposals::{propose_scan_elements, ScanProposalOptions};
6use ifc_lite_processing::scan_segmentation::ScanSegmentationReport;
7use wasm_bindgen::prelude::*;
8
9const MAX_OPTIONS_BYTES: usize = 64 * 1024;
10const MAX_REPORT_BYTES: usize = 64 * 1024 * 1024;
12
13fn propose_json(report_json: &str, options_json: &str) -> Result<Vec<u8>, String> {
14 if options_json.len() > MAX_OPTIONS_BYTES {
15 return Err("Scan proposal options exceed 64 KiB".into());
16 }
17 if report_json.len() > MAX_REPORT_BYTES {
18 return Err("Scan segmentation report exceeds 64 MiB".into());
19 }
20 let options: ScanProposalOptions = serde_json::from_str(options_json)
21 .map_err(|error| format!("Invalid scan proposal options: {error}"))?;
22 let report: ScanSegmentationReport = serde_json::from_str(report_json)
23 .map_err(|error| format!("Invalid scan segmentation report: {error}"))?;
24 let proposals = propose_scan_elements(&report, &options)?;
25 serde_json::to_vec(&proposals).map_err(|error| format!("Cannot encode scan proposals: {error}"))
26}
27
28#[wasm_bindgen]
29impl IfcAPI {
30 #[wasm_bindgen(js_name = proposeScanElements)]
37 pub fn propose_scan_elements(&self, report_json: &str, options_json: &str) -> Result<Vec<u8>, JsError> {
38 propose_json(report_json, options_json).map_err(|message| JsError::new(&message))
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::propose_json;
45 use crate::api::scan_segmentation::segment_json;
46
47 #[test]
48 fn issue_6894_proposal_binding_round_trips_a_segmentation_report_and_is_strict() {
49 let empty = String::from_utf8(segment_json(&[0., 0., 0.], "{}").unwrap()).unwrap();
50 let report: serde_json::Value = serde_json::from_slice(&propose_json(&empty, "{}").unwrap()).unwrap();
51 assert_eq!(report["algorithm"], "ifclite-scan-proposals-v1");
52 assert_eq!(report["proposals"].as_array().map(Vec::len), Some(0));
53 assert!(propose_json(&empty, r#"{"surprise":1}"#).unwrap_err().contains("Invalid scan proposal options"));
54 assert!(propose_json("{}", "{}").unwrap_err().contains("Invalid scan segmentation report"));
55 assert!(propose_json(&empty, &" ".repeat(64 * 1024 + 1)).unwrap_err().contains("64 KiB"));
56 assert!(propose_json(&empty, r#"{"scanToModel":[-1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]}"#).unwrap_err().contains("reflect"));
57 }
58}