chore: cleanup pass — remove empty types stub, implement superblock v4, reconcile plan docs

- Remove clawhdf5-types (empty 1-line stub crate; type defs already live in
  clawhdf5-format). Update workspace Cargo.toml and CLAUDE.md accordingly.
- Implement HDF5 superblock v4 (page-buffer mode) read and write support in
  clawhdf5-format: Superblock::parse_v4, page_size field, v4 serialize
  branch, and FileWriter::with_page_size. This was the one task left
  unimplemented from docs/superpowers/plans/2026-06-29-format-write-extensions.md.
- Reconcile the three docs/superpowers/plans/*.md docs (filter codecs,
  format write extensions, MPI-IO VOL) against actual shipped code: they
  were pre-work plans for d6c4d4f (2026-06-30) committed to git late on
  2026-08-03 with all checkboxes still unchecked. Mark completed tasks done
  and add a status note so they read as historical records, not open work.
- Refresh ROADMAP.md's "What's Next" section against current repo state.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
Omar Sobh
2026-08-03 08:11:31 -07:00
co-authored by Claude Sonnet 5
parent b1fc23e975
commit 6b1ea450f5
11 changed files with 300 additions and 120 deletions
+47 -3
View File
@@ -932,6 +932,8 @@ pub struct FileWriter {
alignment_threshold: usize,
/// Global alignment boundary in bytes (0 = disabled).
alignment_bytes: usize,
/// Page size for page-buffer mode. When set, a v4 superblock is written.
page_size: Option<u32>,
}
impl Default for FileWriter {
@@ -948,6 +950,7 @@ impl FileWriter {
groups: Vec::new(),
alignment_threshold: 0,
alignment_bytes: 0,
page_size: None,
}
}
@@ -961,6 +964,14 @@ impl FileWriter {
self
}
/// Enable page-buffer mode with the given page size. Writing this causes
/// the file to be written with a v4 superblock (page_size field) instead
/// of the default v3.
pub fn with_page_size(&mut self, page_size: u32) -> &mut Self {
self.page_size = Some(page_size);
self
}
pub fn create_group(&mut self, name: &str) -> GroupBuilder {
GroupBuilder::new(name)
}
@@ -979,6 +990,7 @@ impl FileWriter {
}
pub fn finish(self) -> Result<Vec<u8>, FormatError> {
let page_size = self.page_size;
struct DsFlat {
name: String,
dt: Datatype,
@@ -1271,8 +1283,14 @@ impl FileWriter {
let actual_ds_oh_sizes: Vec<usize> = dummy_blobs.iter().map(|b| b.oh_bytes.len()).collect();
// Pass 2: compute real addresses
let root_group_addr = SUPERBLOCK_SIZE as u64;
let mut cursor2 = SUPERBLOCK_SIZE + root_oh_size;
// v4 superblocks add a 4-byte page_size field before the checksum.
let superblock_size = if page_size.is_some() {
SUPERBLOCK_SIZE + 4
} else {
SUPERBLOCK_SIZE
};
let root_group_addr = superblock_size as u64;
let mut cursor2 = superblock_size + root_oh_size;
// Each group is laid out as: object header, then (if dense) its link
// blob, then (if dense) its attribute blob. Link blobs are sized with
@@ -1445,7 +1463,7 @@ impl FileWriter {
let mut buf = Vec::with_capacity(cursor2);
let sb = Superblock {
version: 3,
version: if page_size.is_some() { 4 } else { 3 },
offset_size: OFFSET_SIZE,
length_size: LENGTH_SIZE,
base_address: 0,
@@ -1459,6 +1477,7 @@ impl FileWriter {
consistency_flags: 0,
superblock_extension_address: Some(u64::MAX),
checksum: None,
page_size,
};
buf.extend_from_slice(&sb.serialize());
@@ -2100,4 +2119,29 @@ mod tests {
other => panic!("expected External link, got {other:?}"),
}
}
#[test]
fn file_writer_v4_superblock() {
let mut fw = FileWriter::new();
fw.with_page_size(4096);
fw.create_dataset("data").with_f64_data(&[1.0, 2.0]);
let bytes = fw.finish().unwrap();
let sig = signature::find_signature(&bytes).unwrap();
let sb = Superblock::parse(&bytes, sig).unwrap();
assert_eq!(sb.version, 4, "expected superblock v4");
assert_eq!(sb.page_size, Some(4096));
}
#[test]
fn file_writer_default_superblock_is_v3() {
let mut fw = FileWriter::new();
fw.create_dataset("data").with_f64_data(&[1.0, 2.0]);
let bytes = fw.finish().unwrap();
let sig = signature::find_signature(&bytes).unwrap();
let sb = Superblock::parse(&bytes, sig).unwrap();
assert_eq!(sb.version, 3);
assert_eq!(sb.page_size, None);
}
}