netcdf-rust
Pure-Rust, read-only decoders for HDF5 and NetCDF. The published library dependency graph has no C libraries or build scripts; internal unsafe is limited to read-only memory mapping and performance-critical decoding/copy paths.
Reference tests, benchmarks, fixture generators, and fuzz targets may use native tooling such as NetCDF-C/HDF5 through dev-only dependencies. Those paths are not part of the library runtime dependency graph.
Crates
| Crate | Description |
|---|---|
hdf5-reader |
Low-level HDF5 decoder (superblock, object headers, B-trees, chunked I/O, filters) |
netcdf-reader |
NetCDF reader supporting CDF-1/2/5 classic and NetCDF-4 (HDF5-backed) formats |
Usage
use ;
let file = open?;
println!;
for var in file.variables?
// Read typed data (works for both classic and NetCDF-4)
let temp: ArrayD = file.read_variable?;
// Type-promoting read (any numeric type → f64)
let data = file.read_variable_as_f64?;
// String variables (classic char arrays and NetCDF-4 NC_STRING)
let names = file.read_variable_as_strings?;
// NetCDF-4 user-defined variables (enum, opaque, compound, array, vlen)
let quality = file.read_variable_user_defined?;
// CF conventions: unpack packed integer data (scale_factor + add_offset)
let unpacked = file.read_variable_unpacked?;
// CF conventions: mask fill values + unpack in one call
let clean = file.read_variable_unpacked_masked?;
// Hyperslab: read a single time step from a 4D variable
let sel = NcSliceInfo ;
let step: ArrayD = file.read_variable_slice?;
// Lazy iteration over time steps
for slice in file.?
// In-memory open with custom NC4 cache/filter options
let bytes = read?;
let file = from_bytes_with_options?;
Using hdf5-reader directly:
use Hdf5File;
let file = open?;
let ds = file.dataset?;
let data: ArrayD = ds.read_array?;
// Hyperslab selection
use ;
let sel = SliceInfo ;
let slice: ArrayD = ds.read_slice?;
// String datasets
let labels = file.dataset?.read_strings?;
Features
HDF5
- Superblock v0-v3 and object header v1/v2 with checksum verification
- Compact, contiguous, and chunked layouts
- All chunk index types: v1/v2 B-tree, single-chunk, implicit, Fixed Array, Extensible Array
- Deflate, shuffle, Fletcher-32, N-Bit, ScaleOffset, and optional LZ4 filters
- Custom filters via
FilterRegistry - Fixed-length strings, HDF5 variable-length strings, and byte-vlen string datasets
- Dense-link resolution, soft-link resolution, optional external-link resolution, committed datatypes, global heap strings, and object references
- SOHM shared-message lookup, fractal heap managed/tiny/huge objects, and external raw data files
- Parallel chunk decoding, chunk caching, and object-header caching
- Range-backed opens via
Storagebackends (BytesStorage,FileStorage,MmapStorage)
NetCDF
- CDF-1, CDF-2, CDF-5, and NetCDF-4
- Automatic format detection
- Unified typed reads across formats
- Unified string reads for classic char arrays and NetCDF-4 string variables
- NetCDF-4 user-defined reads for enum, opaque, compound, fixed-size array, and non-string vlen variables, including custom borrowed decoders
- Type promotion to
f64, unpacking, masking, and combined CF helpers - Coordinate-variable lookup plus CF axis/time discovery when
cfis enabled - Exact CF time decoding for standard, proleptic Gregorian, noleap, all_leap,
360_day, and Julian calendars when
cfis enabled - Slice reads, lazy slice iteration, and parallel NC4 slice reads
- Cache and filter configuration through
NcOpenOptions, including in-memory and storage-backed opens
Parallel-I/O Compatibility
This project reads files. It does not provide distributed parallel I/O APIs.
- PnetCDF-produced CDF-1, CDF-2, and CDF-5 files are supported as ordinary classic-format NetCDF files. PnetCDF's MPI-IO API surface is not implemented.
- NetCDF-C files created with
nc_create_paror Parallel HDF5 are supported when the final file is a normal NetCDF-4/HDF5 file that uses HDF5 features supported byhdf5-reader. Parallel access mode is an open-time API concern, not a persistent file property. - The Rayon APIs in this crate parallelize local decoding and independent byte range reads inside one process. They are not equivalent to MPI-IO collective or independent access modes.
- PnetCDF subfiling is out of scope for now because it is not an ordinary single-file CDF-1/2/5 dataset.
Feature flags
Minimum supported Rust version: 1.81.
[]
= "0.7.0" # CDF-1/2/5 + NetCDF-4 (default)
= { = "0.7.0", = false } # CDF-1/2/5 only
| Flag | Default | Description |
|---|---|---|
netcdf4 |
yes | NetCDF-4 support via hdf5-reader |
rayon |
yes | Parallel chunk reading |
lz4 |
yes | LZ4 filter support (hdf5-reader) |
cf |
no | CF Conventions helpers (axis identification, time decoding, CRS extraction, bounds) |
External Raw Data Files
HDF5 external raw data files are not resolved by default. To allow them for
trusted files, opt in with a resolver rooted at the directory that should
contain the external data. The filesystem resolver rejects absolute paths and
.. components. On Unix, it opens paths relative to the resolver root with
openat and O_NOFOLLOW, so symlinks are rejected rather than followed. The
same confinement is applied by FilesystemExternalLinkResolver when external
links are enabled. On non-Unix platforms, the filesystem resolvers fall back to
canonicalize-then-open and attacker-writable resolver roots are out of scope.
use Path;
use Arc;
use ;
let path = new;
let base_dir = path.parent.unwrap_or_else;
let file = open_with_options?;
Custom filters
Register filters before opening files:
use ;
use FilterRegistry;
let mut registry = new;
registry.register;
let file = open_with_options?;
Testing
# Unit tests (no external dependencies)
# Integration tests with generated fixtures
Small compatibility fixtures under testdata/pnetcdf and testdata/parallel
exercise standard CDF-1/2/5 and NetCDF-4 files matching layouts produced by
PnetCDF and parallel netCDF-C/HDF5 workflows. Reference C generators that use
those external parallel libraries live under testdata/external; they are not
library dependencies.
For reference comparisons and current benchmark results against
georust/netcdf, see docs/benchmark-report.md.
Releasing
See RELEASING.md for the release checklist and the required
publish order for hdf5-reader and netcdf-reader.
Known limitations
- SZIP is not built in (register via
FilterRegistryif needed) - ScaleOffset floating-point E-scale mode is not supported by the HDF5 decoder path
License
MIT OR Apache-2.0