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