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:
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user