feat(tools): h5rs, pure-Rust HDF5 tools (ls, dump, stat, diff, check)

New workspace crate clawhdf5-tools with one binary, h5rs, built only on the
clawhdf5 facade and clawhdf5-format (no libhdf5, no C):

- ls [-r] [-v] FILE[/path]: h5ls's listing (same text in its first two
  columns) plus the datatype; -v adds address, link count, layout and chunk
  index, chunk size, storage, filters, datatype and attributes.
- dump [--json] [-A] [-p] [-d PATH] FILE: h5dump DDL (byte-identical to
  h5dump 1.14.6 on the test files) or hdf5-json.
- stat FILE: h5stat's object/link/rank/layout/filter/attribute counts, raw
  data and total size.
- diff [-r] [-q] [-d D] [-p R] A B [OBJ1 [OBJ2]]: structural and value
  differences, exit 0/1/2 like h5diff.
- check [--data] FILE: walks every object, parses every message, verifies
  the checksums of every v2+ structure (including the fractal heap blocks
  the library never checks), checks chunk indexes against their datasets
  and raw data for out-of-file or overlapping extents; every problem with
  its address.

Values over --max-bytes are reported, not read; dense-storage heaps are
verified before objects are read from them; panics are caught (exit 3).
Tests compare with h5ls, h5stat, h5dump and h5diff and with h5py's values,
and flip the checksum of every checksummed structure in a v1.14-format file.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
osobh
2026-09-26 00:29:28 -05:00
co-authored by Claude Opus 5.5
parent bb78d70b99
commit 310448bfcb
18 changed files with 6550 additions and 0 deletions
+63
View File
@@ -0,0 +1,63 @@
//! `h5rs`: HDF5 command-line tools built on clawhdf5 alone, no libhdf5.
//!
//! The binary's subcommands (`ls`, `dump`, `stat`, `diff`, `check`) live in
//! the modules below; [`run`] dispatches to them. See the crate README for
//! the command reference.
pub mod check;
pub mod cli;
pub mod diff;
pub mod dtype;
pub mod dump;
pub mod h5;
pub mod heap_blocks;
pub mod info;
pub mod ls;
pub mod stat;
pub mod value;
use cli::{Args, Out};
pub const USAGE: &str = "\
h5rs: HDF5 tools in pure Rust (clawhdf5, no libhdf5)
usage: h5rs <command> [options] ...
commands:
ls list objects (like h5ls)
dump print a file's structure and values as DDL or JSON (like h5dump)
stat object, layout, filter and storage statistics (like h5stat)
diff compare two files (like h5diff)
check validate a file's structure and checksums
Run `h5rs <command> --help` for a command's options.";
/// Run `h5rs` with `argv` (without the program name). Returns the exit
/// status.
pub fn run(argv: Vec<String>, out: &mut Out) -> std::io::Result<i32> {
let mut it = argv.into_iter();
let Some(cmd) = it.next() else {
writeln!(out.e, "{USAGE}")?;
return Ok(2);
};
let rest: Vec<String> = it.collect();
match cmd.as_str() {
"ls" => ls::run(&mut Args::new("ls", rest), out),
"dump" => dump::run(&mut Args::new("dump", rest), out),
"stat" => stat::run(&mut Args::new("stat", rest), out),
"diff" => diff::run(&mut Args::new("diff", rest), out),
"check" => check::run(&mut Args::new("check", rest), out),
"-h" | "--help" | "help" => {
writeln!(out.o, "{USAGE}")?;
Ok(0)
}
"-V" | "--version" => {
writeln!(out.o, "h5rs {}", env!("CARGO_PKG_VERSION"))?;
Ok(0)
}
other => {
writeln!(out.e, "h5rs: unknown command {other:?}\n\n{USAGE}")?;
Ok(2)
}
}
}