Portability: WASM, no_std & the C Library¶
hdf5-pure is pure Rust with no C dependencies and no build-time linkage to
libhdf5, which gives it three portability properties that the reference library
cannot offer: it compiles to WebAssembly, it compiles for no_std targets with
alloc, and the files it produces are byte-compatible with the rest of the HDF5
ecosystem. This page covers all three, including what is and is not available
without std.
WebAssembly¶
hdf5-pure builds for wasm32-unknown-unknown with no extra toolchain. The key
fact to get right: the Rust std library is available on that target, so
you keep the default features (which include std). The crate's high-level
reader and writer are gated behind std, so turning default features off would
compile File and FileBuilder away — exactly what you do not want for a
WASM app.
In the browser you use the in-memory path, which never touches a filesystem:
FileBuilder::finish returns the complete file as a
Vec<u8> you can hand to JavaScript, and File::from_bytes parses bytes you
get back.
use hdf5_pure::FileBuilder;
let mut builder = FileBuilder::new();
builder.create_dataset("x").with_f64_data(&[1.0, 2.0]);
let bytes: Vec<u8> = builder.finish().unwrap(); // in memory, no filesystem
Reading is symmetric:
use hdf5_pure::File;
let file = File::from_bytes(bytes).unwrap();
let values = file.dataset("x").unwrap().read_f64().unwrap();
The path-based entry points (File::open, FileBuilder::write, EditSession,
SwmrWriter) still compile for WASM, but they cannot reach a filesystem at
runtime in the browser. Build your WASM code around finish and from_bytes.
Trimming the build
deflate is on by default (a pure-Rust backend, so it compiles to WASM
fine). If you only handle uncompressed datasets you can drop it with
default-features = false, features = ["std", "checksum"] — but keep std,
or the high-level API disappears.
no_std with alloc¶
With the default features off, the crate is #![no_std] and relies only on
alloc — it allocates Vecs and similar but never calls the operating system.
It compiles for freestanding targets, and CI builds thumbv7em-none-eabi to
keep that honest.
There is an important limitation today. The high-level, path-and-image API —
File, FileBuilder, EditSession, SwmrWriter, repack, and the mat
module — is std-gated, so a pure-no_std build (--no-default-features)
compiles but does not expose the whole-file reader and writer. What stays
available without std is the lower-level surface: the datatype constructors
(make_f64_type and friends), the DatasetBuilder / GroupBuilder and the
compound/enum type builders, ScaleOffset, and the format primitives. So
no_std is a supported compilation target for embedding the format
machinery; building or reading a complete file still needs std — which, as
shown above, is available on wasm32-unknown-unknown.
| Capability | API | Requires std |
|---|---|---|
| Datatype & builder primitives | make_*_type, DatasetBuilder, GroupBuilder, ScaleOffset |
no (alloc only) |
| Build a whole file in memory | FileBuilder::new / FileBuilder::finish |
yes |
| Parse a file from memory | File::from_bytes |
yes |
| Open a file by path | File::open |
yes |
| Streaming read by path | File::open_streaming |
yes |
| SWMR follow read by path | File::open_swmr |
yes |
| Write a file to a path | FileBuilder::write |
yes |
| Edit a file in place | EditSession |
yes |
| Append in SWMR mode | SwmrWriter |
yes |
| Compact a file | repack |
yes |
MATLAB .mat via serde |
mat module |
yes (serde) |
| N-dimensional array I/O | with_ndarray / read_array |
yes (ndarray) |
Note
The ndarray and serde features both imply std, because they build on
the path-based File / Dataset reader and writer APIs. See the
features reference for the full feature matrix
and the installation guide for
dependency setup.
Reference-library interoperability¶
hdf5-pure does not define its own dialect of HDF5: it writes and reads the
standard on-disk format. Files this crate writes are readable by the reference
HDF5 C library, by h5py, and by MATLAB; files those tools produce are readable
here. This holds for the format features the crate supports — multiple
superblock versions, object header layouts, contiguous and chunked storage, and
the built-in deflate, shuffle, and scale-offset filters.
Interoperability is not asserted by hand. It is enforced by byte-level
crosscheck tests that compare the bytes this crate emits against fixtures
produced by the reference toolchain, so a regression in the on-disk layout fails
the test suite rather than slipping out as a quietly incompatible file. The same
discipline backs the optional ZFP filter
(src/zfp_crosscheck.rs compares against h5py + hdf5plugin) and the MATLAB
.mat path. For the cross-tool story in depth, see the
MATLAB interop page.
32-bit safety¶
The same crosscheck discipline extends to 32-bit hosts. Every offset and length
read out of a file is narrowed through checked conversions, so a 64-bit value
that does not fit a 32-bit usize produces an error rather than a silent
truncation. This is why a file too large for 32-bit address space should be read
with File::open_streaming (see streaming) instead of
File::open. CI exercises the suite on i686 under QEMU.
Memory safety¶
The crate is almost entirely safe Rust. The only non-trivial unsafe is the
cache-line-aligned chunk buffer in the chunk cache, and it is exercised under
Miri with strict provenance in CI. The architecture page
covers the safety and robustness guarantees in more detail.