Skip to content

WASM support? #65

@bluenote10

Description

@bluenote10

First of all, thanks for maintaining this library, this is quite awesome!

I was wondering if it would be feasible to officially support wasm? Ignoring zip support, it looks like it might be doable, but I'm not sure how much effort it really is. I made this minimal experiment:

fn main() {
    let data = include_bytes!("test.npy").as_slice();
    let npy = npyz::NpyFile::new(data).unwrap();
    println!("{} {:?}", npy.len(), npy.shape());
}

with a tiny test.npy generated via:

import numpy as np
np.save("test.npy", np.array([1, 2, 3]))

Trying to compile it with cargo build --target wasm32-unknown-unknown currently fails to compile:

514 |     const SAFE_U16_CUTOFF: usize = 0x1_0000_0000 - 0x400;
    |                                    ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `0_usize - 1024_usize`, which would overflow

Simply replacing the expression in line

const SAFE_U16_CUTOFF: usize = 0x1_0000_0000 - 0x400;

by 0xffff_fc00 seems to fix that issue and the compilation now succeeds.

I'm a bit unsure if this is all that is needed to properly support wasm though. Runtime testing is a bit tedious with wasm apparently. I extended the minimal example to become executable under nodejs by using wasm-pack test

#[wasm_bindgen_test::wasm_bindgen_test]
fn test_wasm() {
    console_error_panic_hook::set_once();

    let data = include_bytes!("test.npy").as_slice();
    let npy = npyz::NpyFile::new(data).unwrap();
    web_log::println!("{} {:?}", npy.len(), npy.shape());

    assert_eq!(npy.len(), 3);
    assert_eq!(npy.shape(), [3]);

    let values: Vec<_> = npy
        .data::<i64>()
        .unwrap()
        .into_iter()
        .map(|value| value.unwrap())
        .collect();

    assert_eq!(values, vec![1, 2, 3]);
}

with appropriate dependencies added to Cargo.toml:

[dependencies]

console_error_panic_hook = "0.1.7"
npyz = {path = "<path-to-my-fork>", features = []}
wasm-bindgen = "0.2.86"
wasm-bindgen-test = "0.3.36"
web-log = "1.0.1"

Running wasm-pack test --node executes the test successfully! But admittedly that is a very tiny bit of functionality tested. It would be interesting to actually run the existing tests against wasm, but that seems tricky, because to my knowledge the regular #[test] tests cannot be easily executed in wasm, and duplicating all tests for tagging them with #[wasm_bindgen_test::wasm_bindgen_test] is also a no go.

Any thoughts on how to proceed? I could open a PR to fix the compile time support, but I'm still a bit uncertain if it actually works and how to verify it systematically...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions