# hdf5-pure
Pure-Rust HDF5 reader/writer. No C dependencies, no build scripts, WASM-compatible.
## Features
- **Write** HDF5 files with datasets, groups, attributes, and nested hierarchies
- **Read** HDF5 files (v0/v1/v2/v3 superblocks, v1/v2 object headers, contiguous/chunked/compact storage)
- **No C dependencies** — compiles to `wasm32-unknown-unknown` with `--no-default-features`
- **MATLAB v7.3 compatible** — userblock support, fixed-length ASCII attributes, variable-length string arrays, object references
- Deflate and shuffle compression
- Compound types, enumerations, array types
- Complex number datasets (as compound `{real, imag}`)
## Quick start
### Writing
```rust
use hdf5_pure::{FileBuilder, AttrValue};
let mut builder = FileBuilder::new();
// Datasets
builder.create_dataset("temperature")
.with_f64_data(&[22.5, 23.1, 21.8])
.with_shape(&[3]);
// Groups with nested datasets
let mut grp = builder.create_group("sensors");
grp.create_dataset("pressure").with_f32_data(&[101.3, 101.5]);
grp.set_attr("location", AttrValue::AsciiString("lab_a".into()));
builder.add_group(grp.finish());
// Attributes on the root group
builder.set_attr("version", AttrValue::I64(2));
builder.write("output.h5").unwrap();
```
### Reading
```rust
use hdf5_pure::File;
let file = File::open("output.h5").unwrap();
let ds = file.dataset("temperature").unwrap();
println!("shape: {:?}", ds.shape().unwrap()); // [3]
println!("data: {:?}", ds.read_f64().unwrap()); // [22.5, 23.1, 21.8]
let attrs = file.root().attrs().unwrap();
println!("version: {:?}", attrs.get("version")); // Some(I64(2))
```
### In-memory (WASM)
```rust
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(); // no filesystem needed
```
## Supported data types
### Datasets
| `with_f64_data` | IEEE 64-bit float |
| `with_f32_data` | IEEE 32-bit float |
| `with_i8_data` / `with_i16_data` / `with_i32_data` / `with_i64_data` | Signed integers |
| `with_u8_data` / `with_u16_data` / `with_u32_data` / `with_u64_data` | Unsigned integers |
| `with_complex32_data` | Compound `{real: f32, imag: f32}` |
| `with_complex64_data` | Compound `{real: f64, imag: f64}` |
| `with_compound_data` | Arbitrary compound types |
| `with_enum_i32_data` / `with_enum_u8_data` | Enumeration types |
| `with_array_data` | Fixed-size array types |
| `with_path_references` | Object references (resolved by path) |
| `with_dtype` + `with_shape` | Empty/zero-dimension datasets |
### Attributes
| `AttrValue::F64` / `F64Array` | 64-bit float scalar/array |
| `AttrValue::I32` / `I64` / `I64Array` | Signed integer scalar/array |
| `AttrValue::U32` / `U64` | Unsigned integer scalar |
| `AttrValue::String` / `StringArray` | UTF-8 null-padded string |
| `AttrValue::AsciiString` | Fixed-length ASCII string |
| `AttrValue::VarLenAsciiArray` | Variable-length ASCII string array (global heap) |
## Compression
```rust
// Deflate (zlib)
builder.create_dataset("compressed")
.with_f64_data(&data)
.with_chunks(&[100])
.with_deflate(6);
// Shuffle + deflate
builder.create_dataset("shuffled")
.with_f64_data(&data)
.with_chunks(&[100])
.with_shuffle()
.with_deflate(6);
```
## Userblock (MATLAB v7.3)
```rust
let mut builder = FileBuilder::new();
builder.with_userblock(512);
builder.create_dataset("data").with_f64_data(&[1.0]);
let mut bytes = builder.finish().unwrap();
// Write MATLAB header into userblock
bytes[126] = b'I';
bytes[127] = b'M';
```
## MATLAB struct pattern
```rust
use hdf5_pure::{FileBuilder, AttrValue};
let mut builder = FileBuilder::new();
let mut grp = builder.create_group("my_struct");
let mut fields = Vec::new();
for (name, data) in [("x", vec![1.0, 2.0]), ("y", vec![3.0, 4.0])] {
fields.push(name.to_string());
grp.create_dataset(name).with_f64_data(&data)
.set_attr("MATLAB_class", AttrValue::AsciiString("double".into()));
}
grp.set_attr("MATLAB_class", AttrValue::AsciiString("struct".into()));
grp.set_attr("MATLAB_fields", AttrValue::VarLenAsciiArray(fields));
builder.add_group(grp.finish());
```
## Cargo features
| `std` | yes | File I/O, high-level reader API |
| `checksum` | yes | Jenkins hash for v2+ object headers |
| `deflate` | yes | Deflate compression (pure Rust backend) |
| `fast-checksum` | no | Hardware-accelerated CRC32 via `crc32fast` |
| `fast-deflate` | no | zlib-ng backend for deflate via `flate2/zlib-ng` |
| `mmap` | no | Memory-mapped file reading via `memmap2` |
| `parallel` | no | Parallel chunk processing via `rayon` |
| `provenance` | no | SHA-256 data provenance tracking |
For WASM, disable default features:
```toml
[dependencies]
hdf5-pure = { version = "0.1", default-features = false, features = ["checksum"] }
```
## Acknowledgements
The HDF5 format parsing and low-level I/O modules are derived from [rustyhdf5](https://github.com/rustystack/rustyhdf5) by the RustyStack project (MIT licensed).
## License
MIT