numcodecs_wasm/
engine.rs

1use pyo3::prelude::*;
2
3#[cfg(not(target_arch = "wasm32"))]
4pub type Engine = wasmtime_runtime_layer::Engine;
5
6#[cfg(not(target_arch = "wasm32"))]
7pub fn default_engine(py: Python) -> Result<Engine, PyErr> {
8    use pyo3_error::PyErrChain;
9
10    // codecs don't need to preallocate the full 4GB wasm32 memory space, but
11    //  still give them a reasonable static allocation for better codegen
12    const WASM_PAGE_SIZE: u32 = 0x10000 /* 64kiB */;
13    const MEMORY_RESERVATION: u32 = WASM_PAGE_SIZE * 16 * 64 /* 64MiB */;
14    const MEMORY_GUARD_SIZE: u32 = WASM_PAGE_SIZE * 16 * 64 /* 64MiB */;
15    const MEMORY_RESERVATION_FOR_GROWTH: u32 = WASM_PAGE_SIZE * 16 * 64 /* 64MiB */;
16
17    let mut config = wasmtime::Config::new();
18    config
19        .cranelift_nan_canonicalization(true)
20        .cranelift_opt_level(wasmtime::OptLevel::Speed)
21        .memory_reservation(u64::from(MEMORY_RESERVATION))
22        .memory_guard_size(u64::from(MEMORY_GUARD_SIZE))
23        .memory_reservation_for_growth(u64::from(MEMORY_RESERVATION_FOR_GROWTH))
24        // WASM feature restrictions, follows the feature validation in
25        //  numcodecs_wasm_host_reproducible::engine::ValidatedModule::new
26        .wasm_bulk_memory(true)
27        .wasm_custom_page_sizes(false)
28        .wasm_extended_const(false)
29        .wasm_function_references(false)
30        .wasm_gc(false)
31        .wasm_memory64(false)
32        .wasm_multi_memory(true)
33        .wasm_multi_value(true)
34        .wasm_reference_types(false)
35        .wasm_relaxed_simd(false)
36        .wasm_simd(true)
37        .wasm_tail_call(false)
38        // wasmtime is compiled without the `threads` feature
39        // .wasm_threads(false)
40        .wasm_wide_arithmetic(true);
41
42    // TODO: allow configuration to be taken from somewhere else
43    config
44        .cache_config_load_default()
45        .map_err(|err| PyErrChain::new(py, err))?;
46
47    let engine = wasmtime::Engine::new(&config).map_err(|err| PyErrChain::new(py, err))?;
48
49    Ok(Engine::new(engine))
50}
51
52#[cfg(target_arch = "wasm32")]
53pub type Engine = pyodide_webassembly_runtime_layer::Engine;
54
55#[cfg(target_arch = "wasm32")]
56#[expect(clippy::unnecessary_wraps)]
57pub fn default_engine(_py: Python) -> Result<Engine, PyErr> {
58    Ok(Engine::default())
59}