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,45 @@
|
||||
//! Argument handling and output plumbing shared by the subcommands.
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
/// Where a subcommand writes: `o` for results, `e` for diagnostics.
|
||||
pub struct Out<'a> {
|
||||
pub o: &'a mut dyn Write,
|
||||
pub e: &'a mut dyn Write,
|
||||
}
|
||||
|
||||
/// The arguments after the subcommand name.
|
||||
pub struct Args {
|
||||
cmd: &'static str,
|
||||
rest: std::vec::IntoIter<String>,
|
||||
}
|
||||
|
||||
impl Args {
|
||||
pub fn new(cmd: &'static str, rest: Vec<String>) -> Self {
|
||||
Self {
|
||||
cmd,
|
||||
rest: rest.into_iter(),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn next(&mut self) -> Option<String> {
|
||||
self.rest.next()
|
||||
}
|
||||
|
||||
/// The value after an option such as `--max-bytes`.
|
||||
pub fn value(&mut self) -> Option<String> {
|
||||
self.rest.next()
|
||||
}
|
||||
|
||||
/// A numeric option value.
|
||||
pub fn number<T: std::str::FromStr>(&mut self) -> Option<T> {
|
||||
self.rest.next().and_then(|s| s.parse().ok())
|
||||
}
|
||||
|
||||
/// Report a usage problem; exit status 2.
|
||||
pub fn usage_error(&self, out: &mut Out, msg: &str, usage: &str) -> std::io::Result<i32> {
|
||||
writeln!(out.e, "h5rs {}: {msg}\n\n{usage}", self.cmd)?;
|
||||
Ok(2)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user