1use wasmtime::{Engine, Instance, Linker, Memory, Module, Store, TypedFunc};
7
8use crate::error::{OcctError, OcctResult};
9use crate::kernel_generated::GeneratedFuncs;
10use crate::types::{
11 BoundingBox, EdgeData, EvolutionData, LabelInfo, Mesh, MeshBatch, NurbsCurveData,
12 ProjectionData, ShapeHandle, Vec3,
13};
14
15static WASM_BINARY: &[u8] = include_bytes!("occt-wasm.wasm.br");
20
21pub struct OcctKernel {
38 pub(crate) store: Store<()>,
39 pub(crate) instance: Instance,
40 pub(crate) memory: Memory,
41
42 pub(crate) fn_has_error: TypedFunc<(), i32>,
44 pub(crate) fn_get_error: TypedFunc<(), i32>,
45 pub(crate) fn_get_error_len: TypedFunc<(), u32>,
46
47 pub(crate) fn_alloc: TypedFunc<u32, u32>,
49 pub(crate) fn_free: TypedFunc<u32, ()>,
50
51 pub(crate) fn_get_string_result: TypedFunc<(), i32>,
53 pub(crate) fn_get_string_result_len: TypedFunc<(), u32>,
54 pub(crate) fn_get_vec_u32_result: TypedFunc<(), i32>,
55 pub(crate) fn_get_vec_u32_result_len: TypedFunc<(), u32>,
56 pub(crate) fn_get_vec_f64_result: TypedFunc<(), i32>,
57 pub(crate) fn_get_vec_f64_result_len: TypedFunc<(), u32>,
58 pub(crate) fn_get_vec_i32_result: TypedFunc<(), i32>,
59 pub(crate) fn_get_vec_i32_result_len: TypedFunc<(), u32>,
60
61 pub(crate) fn_get_bbox_xmin: TypedFunc<(), f64>,
63 pub(crate) fn_get_bbox_ymin: TypedFunc<(), f64>,
64 pub(crate) fn_get_bbox_zmin: TypedFunc<(), f64>,
65 pub(crate) fn_get_bbox_xmax: TypedFunc<(), f64>,
66 pub(crate) fn_get_bbox_ymax: TypedFunc<(), f64>,
67 pub(crate) fn_get_bbox_zmax: TypedFunc<(), f64>,
68
69 pub(crate) fn_get_mesh_positions: TypedFunc<(), i32>,
71 pub(crate) fn_get_mesh_positions_len: TypedFunc<(), i32>,
72 pub(crate) fn_get_mesh_normals: TypedFunc<(), i32>,
73 pub(crate) fn_get_mesh_normals_len: TypedFunc<(), i32>,
74 pub(crate) fn_get_mesh_indices: TypedFunc<(), i32>,
75 pub(crate) fn_get_mesh_indices_len: TypedFunc<(), i32>,
76 pub(crate) fn_get_mesh_face_groups: TypedFunc<(), i32>,
77 pub(crate) fn_get_mesh_face_groups_len: TypedFunc<(), i32>,
78
79 pub(crate) fn_get_mesh_batch_positions: TypedFunc<(), i32>,
81 pub(crate) fn_get_mesh_batch_positions_len: TypedFunc<(), i32>,
82 pub(crate) fn_get_mesh_batch_normals: TypedFunc<(), i32>,
83 pub(crate) fn_get_mesh_batch_normals_len: TypedFunc<(), i32>,
84 pub(crate) fn_get_mesh_batch_indices: TypedFunc<(), i32>,
85 pub(crate) fn_get_mesh_batch_indices_len: TypedFunc<(), i32>,
86 pub(crate) fn_get_mesh_batch_shape_offsets: TypedFunc<(), i32>,
87 pub(crate) fn_get_mesh_batch_shape_count: TypedFunc<(), i32>,
88
89 pub(crate) fn_get_edge_points: TypedFunc<(), i32>,
91 pub(crate) fn_get_edge_points_len: TypedFunc<(), i32>,
92 pub(crate) fn_get_edge_groups: TypedFunc<(), i32>,
93 pub(crate) fn_get_edge_groups_len: TypedFunc<(), i32>,
94
95 pub(crate) fn_get_nurbs_degree: TypedFunc<(), i32>,
97 pub(crate) fn_get_nurbs_rational: TypedFunc<(), i32>,
98 pub(crate) fn_get_nurbs_periodic: TypedFunc<(), i32>,
99 pub(crate) fn_get_nurbs_knots: TypedFunc<(), i32>,
100 pub(crate) fn_get_nurbs_knots_len: TypedFunc<(), u32>,
101 pub(crate) fn_get_nurbs_multiplicities: TypedFunc<(), i32>,
102 pub(crate) fn_get_nurbs_multiplicities_len: TypedFunc<(), u32>,
103 pub(crate) fn_get_nurbs_poles: TypedFunc<(), i32>,
104 pub(crate) fn_get_nurbs_poles_len: TypedFunc<(), u32>,
105 pub(crate) fn_get_nurbs_weights: TypedFunc<(), i32>,
106 pub(crate) fn_get_nurbs_weights_len: TypedFunc<(), u32>,
107
108 pub(crate) fn_get_evo_result_id: TypedFunc<(), u32>,
110 pub(crate) fn_get_evo_modified: TypedFunc<(), i32>,
111 pub(crate) fn_get_evo_modified_len: TypedFunc<(), u32>,
112 pub(crate) fn_get_evo_generated: TypedFunc<(), i32>,
113 pub(crate) fn_get_evo_generated_len: TypedFunc<(), u32>,
114 pub(crate) fn_get_evo_deleted: TypedFunc<(), i32>,
115 pub(crate) fn_get_evo_deleted_len: TypedFunc<(), u32>,
116
117 pub(crate) fn_get_proj_visible_outline: TypedFunc<(), u32>,
119 pub(crate) fn_get_proj_visible_smooth: TypedFunc<(), u32>,
120 pub(crate) fn_get_proj_visible_sharp: TypedFunc<(), u32>,
121 pub(crate) fn_get_proj_hidden_outline: TypedFunc<(), u32>,
122 pub(crate) fn_get_proj_hidden_smooth: TypedFunc<(), u32>,
123 pub(crate) fn_get_proj_hidden_sharp: TypedFunc<(), u32>,
124
125 pub(crate) fn_get_label_info_label_id: TypedFunc<(), i32>,
127 pub(crate) fn_get_label_info_name: TypedFunc<(), i32>,
128 pub(crate) fn_get_label_info_name_len: TypedFunc<(), u32>,
129 pub(crate) fn_get_label_info_has_color: TypedFunc<(), i32>,
130 pub(crate) fn_get_label_info_r: TypedFunc<(), f64>,
131 pub(crate) fn_get_label_info_g: TypedFunc<(), f64>,
132 pub(crate) fn_get_label_info_b: TypedFunc<(), f64>,
133 pub(crate) fn_get_label_info_is_assembly: TypedFunc<(), i32>,
134 pub(crate) fn_get_label_info_is_component: TypedFunc<(), i32>,
135 pub(crate) fn_get_label_info_shape_id: TypedFunc<(), u32>,
136
137 pub(crate) generated: GeneratedFuncs,
139}
140
141impl OcctKernel {
142 #[allow(clippy::too_many_lines)]
148 pub fn new() -> OcctResult<Self> {
149 let mut config = wasmtime::Config::new();
150 config.wasm_simd(true);
151 config.wasm_tail_call(true);
152 config.wasm_relaxed_simd(true);
153 config.wasm_exceptions(true);
156
157 let engine = Engine::new(&config)?;
158 let wasm_bytes = decompress_wasm()?;
159 let module = Module::new(&engine, &wasm_bytes)?;
160 let mut store = Store::new(&engine, ());
161 let linker = Linker::new(&engine);
162 let instance = linker.instantiate(&mut store, &module)?;
163
164 let memory = instance
165 .get_memory(&mut store, "memory")
166 .ok_or_else(|| OcctError::Memory("no memory export".to_owned()))?;
167
168 let init: TypedFunc<(), i32> = instance.get_typed_func(&mut store, "occt_init")?;
170 let result = init.call(&mut store, ())?;
171 if result != 0 {
172 return Err(OcctError::Memory("occt_init failed".to_owned()));
173 }
174
175 macro_rules! get_fn {
177 ($name:expr => $ret:ty) => {
178 instance.get_typed_func::<(), $ret>(&mut store, $name)?
179 };
180 ($name:expr, $param:ty => $ret:ty) => {
181 instance.get_typed_func::<$param, $ret>(&mut store, $name)?
182 };
183 }
184
185 let generated = GeneratedFuncs::resolve(&instance, &mut store)?;
186
187 Ok(Self {
188 memory,
189 instance,
190
191 fn_has_error: get_fn!("occt_has_error" => i32),
192 fn_get_error: get_fn!("occt_get_error" => i32),
193 fn_get_error_len: get_fn!("occt_get_error_len" => u32),
194 fn_alloc: get_fn!("occt_alloc", u32 => u32),
195 fn_free: get_fn!("occt_free", u32 => ()),
196
197 fn_get_string_result: get_fn!("occt_get_string_result" => i32),
198 fn_get_string_result_len: get_fn!("occt_get_string_result_len" => u32),
199 fn_get_vec_u32_result: get_fn!("occt_get_vec_u32_result" => i32),
200 fn_get_vec_u32_result_len: get_fn!("occt_get_vec_u32_result_len" => u32),
201 fn_get_vec_f64_result: get_fn!("occt_get_vec_f64_result" => i32),
202 fn_get_vec_f64_result_len: get_fn!("occt_get_vec_f64_result_len" => u32),
203 fn_get_vec_i32_result: get_fn!("occt_get_vec_i32_result" => i32),
204 fn_get_vec_i32_result_len: get_fn!("occt_get_vec_i32_result_len" => u32),
205
206 fn_get_bbox_xmin: get_fn!("occt_get_bbox_xmin" => f64),
207 fn_get_bbox_ymin: get_fn!("occt_get_bbox_ymin" => f64),
208 fn_get_bbox_zmin: get_fn!("occt_get_bbox_zmin" => f64),
209 fn_get_bbox_xmax: get_fn!("occt_get_bbox_xmax" => f64),
210 fn_get_bbox_ymax: get_fn!("occt_get_bbox_ymax" => f64),
211 fn_get_bbox_zmax: get_fn!("occt_get_bbox_zmax" => f64),
212
213 fn_get_mesh_positions: get_fn!("occt_get_mesh_positions" => i32),
214 fn_get_mesh_positions_len: get_fn!("occt_get_mesh_positions_len" => i32),
215 fn_get_mesh_normals: get_fn!("occt_get_mesh_normals" => i32),
216 fn_get_mesh_normals_len: get_fn!("occt_get_mesh_normals_len" => i32),
217 fn_get_mesh_indices: get_fn!("occt_get_mesh_indices" => i32),
218 fn_get_mesh_indices_len: get_fn!("occt_get_mesh_indices_len" => i32),
219 fn_get_mesh_face_groups: get_fn!("occt_get_mesh_face_groups" => i32),
220 fn_get_mesh_face_groups_len: get_fn!("occt_get_mesh_face_groups_len" => i32),
221
222 fn_get_mesh_batch_positions: get_fn!("occt_get_mesh_batch_positions" => i32),
223 fn_get_mesh_batch_positions_len: get_fn!("occt_get_mesh_batch_positions_len" => i32),
224 fn_get_mesh_batch_normals: get_fn!("occt_get_mesh_batch_normals" => i32),
225 fn_get_mesh_batch_normals_len: get_fn!("occt_get_mesh_batch_normals_len" => i32),
226 fn_get_mesh_batch_indices: get_fn!("occt_get_mesh_batch_indices" => i32),
227 fn_get_mesh_batch_indices_len: get_fn!("occt_get_mesh_batch_indices_len" => i32),
228 fn_get_mesh_batch_shape_offsets: get_fn!("occt_get_mesh_batch_shape_offsets" => i32),
229 fn_get_mesh_batch_shape_count: get_fn!("occt_get_mesh_batch_shape_count" => i32),
230
231 fn_get_edge_points: get_fn!("occt_get_edge_points" => i32),
232 fn_get_edge_points_len: get_fn!("occt_get_edge_points_len" => i32),
233 fn_get_edge_groups: get_fn!("occt_get_edge_groups" => i32),
234 fn_get_edge_groups_len: get_fn!("occt_get_edge_groups_len" => i32),
235
236 fn_get_nurbs_degree: get_fn!("occt_get_nurbs_degree" => i32),
237 fn_get_nurbs_rational: get_fn!("occt_get_nurbs_rational" => i32),
238 fn_get_nurbs_periodic: get_fn!("occt_get_nurbs_periodic" => i32),
239 fn_get_nurbs_knots: get_fn!("occt_get_nurbs_knots" => i32),
240 fn_get_nurbs_knots_len: get_fn!("occt_get_nurbs_knots_len" => u32),
241 fn_get_nurbs_multiplicities: get_fn!("occt_get_nurbs_multiplicities" => i32),
242 fn_get_nurbs_multiplicities_len: get_fn!("occt_get_nurbs_multiplicities_len" => u32),
243 fn_get_nurbs_poles: get_fn!("occt_get_nurbs_poles" => i32),
244 fn_get_nurbs_poles_len: get_fn!("occt_get_nurbs_poles_len" => u32),
245 fn_get_nurbs_weights: get_fn!("occt_get_nurbs_weights" => i32),
246 fn_get_nurbs_weights_len: get_fn!("occt_get_nurbs_weights_len" => u32),
247
248 fn_get_evo_result_id: get_fn!("occt_get_evo_result_id" => u32),
249 fn_get_evo_modified: get_fn!("occt_get_evo_modified" => i32),
250 fn_get_evo_modified_len: get_fn!("occt_get_evo_modified_len" => u32),
251 fn_get_evo_generated: get_fn!("occt_get_evo_generated" => i32),
252 fn_get_evo_generated_len: get_fn!("occt_get_evo_generated_len" => u32),
253 fn_get_evo_deleted: get_fn!("occt_get_evo_deleted" => i32),
254 fn_get_evo_deleted_len: get_fn!("occt_get_evo_deleted_len" => u32),
255
256 fn_get_proj_visible_outline: get_fn!("occt_get_proj_visible_outline" => u32),
257 fn_get_proj_visible_smooth: get_fn!("occt_get_proj_visible_smooth" => u32),
258 fn_get_proj_visible_sharp: get_fn!("occt_get_proj_visible_sharp" => u32),
259 fn_get_proj_hidden_outline: get_fn!("occt_get_proj_hidden_outline" => u32),
260 fn_get_proj_hidden_smooth: get_fn!("occt_get_proj_hidden_smooth" => u32),
261 fn_get_proj_hidden_sharp: get_fn!("occt_get_proj_hidden_sharp" => u32),
262
263 fn_get_label_info_label_id: get_fn!("occt_get_label_info_label_id" => i32),
264 fn_get_label_info_name: get_fn!("occt_get_label_info_name" => i32),
265 fn_get_label_info_name_len: get_fn!("occt_get_label_info_name_len" => u32),
266 fn_get_label_info_has_color: get_fn!("occt_get_label_info_has_color" => i32),
267 fn_get_label_info_r: get_fn!("occt_get_label_info_r" => f64),
268 fn_get_label_info_g: get_fn!("occt_get_label_info_g" => f64),
269 fn_get_label_info_b: get_fn!("occt_get_label_info_b" => f64),
270 fn_get_label_info_is_assembly: get_fn!("occt_get_label_info_is_assembly" => i32),
271 fn_get_label_info_is_component: get_fn!("occt_get_label_info_is_component" => i32),
272 fn_get_label_info_shape_id: get_fn!("occt_get_label_info_shape_id" => u32),
273
274 generated,
275 store,
276 })
277 }
278
279 pub(crate) fn write_bytes(&mut self, data: &[u8]) -> OcctResult<u32> {
283 let ptr = self.fn_alloc.call(&mut self.store, data.len() as u32)?;
284 if ptr == 0 {
285 core::hint::cold_path();
286 return Err(OcctError::Memory("allocation failed".to_owned()));
287 }
288 let mem = self.memory.data_mut(&mut self.store);
289 let start = ptr as usize;
290 let end = start + data.len();
291 if end > mem.len() {
292 core::hint::cold_path();
293 return Err(OcctError::Memory("write out of bounds".to_owned()));
294 }
295 mem[start..end].copy_from_slice(data);
296 Ok(ptr)
297 }
298
299 pub(crate) fn free_bytes(&mut self, ptr: u32) -> OcctResult<()> {
301 self.fn_free.call(&mut self.store, ptr)?;
302 Ok(())
303 }
304
305 fn read_bytes(&self, ptr: u32, len: u32) -> OcctResult<Vec<u8>> {
307 let mem = self.memory.data(&self.store);
308 let start = ptr as usize;
309 let end = start + len as usize;
310 if end > mem.len() {
311 core::hint::cold_path();
312 return Err(OcctError::Memory("read out of bounds".to_owned()));
313 }
314 Ok(mem[start..end].to_vec())
315 }
316
317 fn read_f32_slice(&self, ptr: u32, count: u32) -> OcctResult<Vec<f32>> {
319 let bytes = self.read_bytes(ptr, count * 4)?;
320 Ok(bytes
321 .chunks_exact(4)
322 .map(|c| f32::from_le_bytes([c[0], c[1], c[2], c[3]]))
323 .collect())
324 }
325
326 fn read_u32_slice(&self, ptr: u32, count: u32) -> OcctResult<Vec<u32>> {
328 let bytes = self.read_bytes(ptr, count * 4)?;
329 Ok(bytes
330 .chunks_exact(4)
331 .map(|c| u32::from_le_bytes([c[0], c[1], c[2], c[3]]))
332 .collect())
333 }
334
335 fn read_i32_slice(&self, ptr: u32, count: u32) -> OcctResult<Vec<i32>> {
337 let bytes = self.read_bytes(ptr, count * 4)?;
338 Ok(bytes
339 .chunks_exact(4)
340 .map(|c| i32::from_le_bytes([c[0], c[1], c[2], c[3]]))
341 .collect())
342 }
343
344 fn read_f64_slice(&self, ptr: u32, count: u32) -> OcctResult<Vec<f64>> {
346 let bytes = self.read_bytes(ptr, count * 8)?;
347 Ok(bytes
348 .chunks_exact(8)
349 .map(|c| f64::from_le_bytes([c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]]))
350 .collect())
351 }
352
353 pub(crate) fn check_error(&mut self, operation: &str) -> OcctResult<()> {
357 let has_error = self.fn_has_error.call(&mut self.store, ())?;
358 if has_error != 0 {
359 core::hint::cold_path();
363 return Err(self.read_last_error(operation));
364 }
365 Ok(())
366 }
367
368 #[cold]
370 pub(crate) fn read_last_error(&mut self, operation: &str) -> OcctError {
371 let ptr = self.fn_get_error.call(&mut self.store, ()).unwrap_or(0);
372 let len = self.fn_get_error_len.call(&mut self.store, ()).unwrap_or(0);
373 let message = if ptr != 0 && len > 0 {
374 self.read_bytes(ptr as u32, len)
375 .ok()
376 .and_then(|b| String::from_utf8(b).ok())
377 .unwrap_or_else(|| "unknown error".to_owned())
378 } else {
379 "unknown error".to_owned()
380 };
381 OcctError::Operation {
382 operation: operation.to_owned(),
383 message,
384 }
385 }
386
387 pub(crate) fn read_string_result(&mut self) -> OcctResult<String> {
391 let ptr = self.fn_get_string_result.call(&mut self.store, ())?;
392 let len = self.fn_get_string_result_len.call(&mut self.store, ())?;
393 let bytes = self.read_bytes(ptr as u32, len)?;
394 String::from_utf8(bytes).map_err(|e| OcctError::Memory(e.to_string()))
395 }
396
397 pub(crate) fn read_vec_u32_result(&mut self) -> OcctResult<Vec<u32>> {
399 let ptr = self.fn_get_vec_u32_result.call(&mut self.store, ())?;
400 let len = self.fn_get_vec_u32_result_len.call(&mut self.store, ())?;
401 self.read_u32_slice(ptr as u32, len)
402 }
403
404 pub(crate) fn read_vec_f64_result(&mut self) -> OcctResult<Vec<f64>> {
406 let ptr = self.fn_get_vec_f64_result.call(&mut self.store, ())?;
407 let len = self.fn_get_vec_f64_result_len.call(&mut self.store, ())?;
408 self.read_f64_slice(ptr as u32, len)
409 }
410
411 pub(crate) fn read_vec_i32_result(&mut self) -> OcctResult<Vec<i32>> {
413 let ptr = self.fn_get_vec_i32_result.call(&mut self.store, ())?;
414 let len = self.fn_get_vec_i32_result_len.call(&mut self.store, ())?;
415 self.read_i32_slice(ptr as u32, len)
416 }
417
418 pub(crate) fn read_bbox_result(&mut self) -> OcctResult<BoundingBox> {
420 Ok(BoundingBox {
421 min: Vec3 {
422 x: self.fn_get_bbox_xmin.call(&mut self.store, ())?,
423 y: self.fn_get_bbox_ymin.call(&mut self.store, ())?,
424 z: self.fn_get_bbox_zmin.call(&mut self.store, ())?,
425 },
426 max: Vec3 {
427 x: self.fn_get_bbox_xmax.call(&mut self.store, ())?,
428 y: self.fn_get_bbox_ymax.call(&mut self.store, ())?,
429 z: self.fn_get_bbox_zmax.call(&mut self.store, ())?,
430 },
431 })
432 }
433
434 pub(crate) fn read_mesh_result(&mut self) -> OcctResult<Mesh> {
436 let pos_ptr = self.fn_get_mesh_positions.call(&mut self.store, ())?;
437 let pos_len = self.fn_get_mesh_positions_len.call(&mut self.store, ())?;
438 let norm_ptr = self.fn_get_mesh_normals.call(&mut self.store, ())?;
439 let norm_len = self.fn_get_mesh_normals_len.call(&mut self.store, ())?;
440 let idx_ptr = self.fn_get_mesh_indices.call(&mut self.store, ())?;
441 let idx_len = self.fn_get_mesh_indices_len.call(&mut self.store, ())?;
442 let fg_ptr = self.fn_get_mesh_face_groups.call(&mut self.store, ())?;
443 let fg_len = self.fn_get_mesh_face_groups_len.call(&mut self.store, ())?;
444
445 Ok(Mesh {
446 positions: self.read_f32_slice(pos_ptr as u32, pos_len as u32)?,
447 normals: self.read_f32_slice(norm_ptr as u32, norm_len as u32)?,
448 indices: self.read_u32_slice(idx_ptr as u32, idx_len as u32)?,
449 face_groups: self.read_i32_slice(fg_ptr as u32, fg_len as u32)?,
450 })
451 }
452
453 pub(crate) fn read_mesh_batch_result(&mut self) -> OcctResult<MeshBatch> {
455 let pos_ptr = self.fn_get_mesh_batch_positions.call(&mut self.store, ())?;
456 let pos_len = self
457 .fn_get_mesh_batch_positions_len
458 .call(&mut self.store, ())?;
459 let norm_ptr = self.fn_get_mesh_batch_normals.call(&mut self.store, ())?;
460 let norm_len = self
461 .fn_get_mesh_batch_normals_len
462 .call(&mut self.store, ())?;
463 let idx_ptr = self.fn_get_mesh_batch_indices.call(&mut self.store, ())?;
464 let idx_len = self
465 .fn_get_mesh_batch_indices_len
466 .call(&mut self.store, ())?;
467 let off_ptr = self
468 .fn_get_mesh_batch_shape_offsets
469 .call(&mut self.store, ())?;
470 let shape_count = self
471 .fn_get_mesh_batch_shape_count
472 .call(&mut self.store, ())?;
473
474 Ok(MeshBatch {
475 positions: self.read_f32_slice(pos_ptr as u32, pos_len as u32)?,
476 normals: self.read_f32_slice(norm_ptr as u32, norm_len as u32)?,
477 indices: self.read_u32_slice(idx_ptr as u32, idx_len as u32)?,
478 shape_offsets: self.read_i32_slice(off_ptr as u32, (shape_count * 4) as u32)?,
479 })
480 }
481
482 pub(crate) fn read_edge_result(&mut self) -> OcctResult<EdgeData> {
484 let pts_ptr = self.fn_get_edge_points.call(&mut self.store, ())?;
485 let pts_len = self.fn_get_edge_points_len.call(&mut self.store, ())?;
486 let grp_ptr = self.fn_get_edge_groups.call(&mut self.store, ())?;
487 let grp_len = self.fn_get_edge_groups_len.call(&mut self.store, ())?;
488
489 Ok(EdgeData {
490 points: self.read_f32_slice(pts_ptr as u32, pts_len as u32)?,
491 edge_groups: self.read_i32_slice(grp_ptr as u32, grp_len as u32)?,
492 })
493 }
494
495 pub(crate) fn read_nurbs_result(&mut self) -> OcctResult<NurbsCurveData> {
497 let degree = self.fn_get_nurbs_degree.call(&mut self.store, ())?;
498 let rational = self.fn_get_nurbs_rational.call(&mut self.store, ())? != 0;
499 let periodic = self.fn_get_nurbs_periodic.call(&mut self.store, ())? != 0;
500
501 let knots_ptr = self.fn_get_nurbs_knots.call(&mut self.store, ())?;
502 let knots_len = self.fn_get_nurbs_knots_len.call(&mut self.store, ())?;
503 let mult_ptr = self.fn_get_nurbs_multiplicities.call(&mut self.store, ())?;
504 let mult_len = self
505 .fn_get_nurbs_multiplicities_len
506 .call(&mut self.store, ())?;
507 let poles_ptr = self.fn_get_nurbs_poles.call(&mut self.store, ())?;
508 let poles_len = self.fn_get_nurbs_poles_len.call(&mut self.store, ())?;
509 let weights_ptr = self.fn_get_nurbs_weights.call(&mut self.store, ())?;
510 let weights_len = self.fn_get_nurbs_weights_len.call(&mut self.store, ())?;
511
512 Ok(NurbsCurveData {
513 degree,
514 rational,
515 periodic,
516 knots: self.read_f64_slice(knots_ptr as u32, knots_len)?,
517 multiplicities: self.read_i32_slice(mult_ptr as u32, mult_len)?,
518 poles: self.read_f64_slice(poles_ptr as u32, poles_len)?,
519 weights: self.read_f64_slice(weights_ptr as u32, weights_len)?,
520 })
521 }
522
523 pub(crate) fn read_evolution_result(&mut self) -> OcctResult<EvolutionData> {
525 let result_id = self.fn_get_evo_result_id.call(&mut self.store, ())?;
526 let mod_ptr = self.fn_get_evo_modified.call(&mut self.store, ())?;
527 let mod_len = self.fn_get_evo_modified_len.call(&mut self.store, ())?;
528 let gen_ptr = self.fn_get_evo_generated.call(&mut self.store, ())?;
529 let gen_len = self.fn_get_evo_generated_len.call(&mut self.store, ())?;
530 let del_ptr = self.fn_get_evo_deleted.call(&mut self.store, ())?;
531 let del_len = self.fn_get_evo_deleted_len.call(&mut self.store, ())?;
532
533 Ok(EvolutionData {
534 result_id,
535 modified: self.read_i32_slice(mod_ptr as u32, mod_len)?,
536 generated: self.read_i32_slice(gen_ptr as u32, gen_len)?,
537 deleted: self.read_i32_slice(del_ptr as u32, del_len)?,
538 })
539 }
540
541 pub(crate) fn read_projection_result(&mut self) -> OcctResult<ProjectionData> {
543 Ok(ProjectionData {
544 visible_outline: ShapeHandle(
545 self.fn_get_proj_visible_outline.call(&mut self.store, ())?,
546 ),
547 visible_smooth: ShapeHandle(self.fn_get_proj_visible_smooth.call(&mut self.store, ())?),
548 visible_sharp: ShapeHandle(self.fn_get_proj_visible_sharp.call(&mut self.store, ())?),
549 hidden_outline: ShapeHandle(self.fn_get_proj_hidden_outline.call(&mut self.store, ())?),
550 hidden_smooth: ShapeHandle(self.fn_get_proj_hidden_smooth.call(&mut self.store, ())?),
551 hidden_sharp: ShapeHandle(self.fn_get_proj_hidden_sharp.call(&mut self.store, ())?),
552 })
553 }
554
555 pub(crate) fn read_label_info_result(&mut self) -> OcctResult<LabelInfo> {
557 let label_id = self.fn_get_label_info_label_id.call(&mut self.store, ())?;
558 let name_ptr = self.fn_get_label_info_name.call(&mut self.store, ())?;
559 let name_len = self.fn_get_label_info_name_len.call(&mut self.store, ())?;
560 let name_bytes = self.read_bytes(name_ptr as u32, name_len)?;
561 let name = String::from_utf8(name_bytes).map_err(|e| OcctError::Memory(e.to_string()))?;
562
563 Ok(LabelInfo {
564 label_id,
565 name,
566 has_color: self.fn_get_label_info_has_color.call(&mut self.store, ())? != 0,
567 r: self.fn_get_label_info_r.call(&mut self.store, ())?,
568 g: self.fn_get_label_info_g.call(&mut self.store, ())?,
569 b: self.fn_get_label_info_b.call(&mut self.store, ())?,
570 is_assembly: self
571 .fn_get_label_info_is_assembly
572 .call(&mut self.store, ())?
573 != 0,
574 is_component: self
575 .fn_get_label_info_is_component
576 .call(&mut self.store, ())?
577 != 0,
578 shape_id: self.fn_get_label_info_shape_id.call(&mut self.store, ())?,
579 })
580 }
581}
582
583impl Drop for OcctKernel {
584 fn drop(&mut self) {
585 if let Ok(destroy) = self
587 .instance
588 .get_typed_func::<(), ()>(&mut self.store, "occt_destroy")
589 {
590 let _ = destroy.call(&mut self.store, ());
591 }
592 }
593}
594
595fn decompress_wasm() -> OcctResult<Vec<u8>> {
597 let mut output = Vec::new();
598 let mut input: &[u8] = WASM_BINARY;
599 brotli::BrotliDecompress(&mut input, &mut output)
600 .map_err(|e| OcctError::Memory(format!("brotli decompression failed: {e}")))?;
601 Ok(output)
602}