clawhdf5: File::storage gives the file's view as a Storage
The bytes File::as_bytes returns (from the superblock on, bounded by the recorded end of file, a metadata cache image laid over), as a &(dyn Storage + Send + Sync) for every backend. Code that parses the file itself with the clawhdf5_format *_in functions — h5rs does — can then read a file opened with File::open_storage (a remote file) as well as a local one; in memory its as_contiguous() is as_bytes(), so local reads stay slices. Test: for every fixture, File::open's storage() is as_bytes() as its contiguous view, and File::open_storage over a read_at-only storage gives the same bytes through storage().read_at. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
@@ -523,6 +523,17 @@ impl File {
|
||||
self.data.contiguous()
|
||||
}
|
||||
|
||||
/// The bytes [`as_bytes`](Self::as_bytes) returns, as a [`Storage`],
|
||||
/// for every backend: from the superblock on, bounded by the recorded
|
||||
/// end of file, with a metadata cache image laid over them. Code that
|
||||
/// parses the file itself with the `clawhdf5_format` `*_in` functions
|
||||
/// reads through this, so it works on remote files too; for a file in
|
||||
/// memory its [`Storage::as_contiguous`] is [`as_bytes`](Self::as_bytes)
|
||||
/// (and every read a slice of it).
|
||||
pub fn storage(&self) -> &(dyn Storage + Send + Sync) {
|
||||
&self.data
|
||||
}
|
||||
|
||||
/// The error of a metadata cache image libhdf5 cannot load, when the
|
||||
/// file has one. Such a file opens, as in libhdf5, and every object
|
||||
/// lookup fails with this error; code that parses [`Self::as_bytes`]
|
||||
|
||||
@@ -432,3 +432,33 @@ fn storage_backed_files_keep_their_zero_copy_views_only_in_memory() {
|
||||
"as_bytes over a range storage must not answer"
|
||||
);
|
||||
}
|
||||
|
||||
/// `File::storage` is the view `as_bytes` gives, for every backend: the
|
||||
/// user block skipped, bounded by the end of file, a cache image laid over.
|
||||
#[test]
|
||||
fn file_storage_is_the_as_bytes_view_for_every_backend() {
|
||||
let root = Path::new(env!("CARGO_MANIFEST_DIR"));
|
||||
let mut files = Vec::new();
|
||||
hdf5_files(&root.join("tests/fixtures"), &mut files);
|
||||
hdf5_files(&root.join("../clawhdf5-format/tests/fixtures"), &mut files);
|
||||
let mut compared = 0;
|
||||
for p in files {
|
||||
let Ok(local) = File::open(&p) else { continue };
|
||||
let bytes = std::fs::read(&p).unwrap();
|
||||
let remote = File::open_storage(Arc::new(CountingStorage::new(bytes))).unwrap();
|
||||
let want = local.as_bytes();
|
||||
let view = local.storage();
|
||||
assert_eq!(view.as_contiguous(), Some(want), "{}", p.display());
|
||||
let got = remote.storage();
|
||||
assert!(got.as_contiguous().is_none());
|
||||
assert_eq!(got.len(), want.len() as u64, "{}", p.display());
|
||||
assert_eq!(
|
||||
&*got.read_at(0, want.len()).unwrap(),
|
||||
want,
|
||||
"{}",
|
||||
p.display()
|
||||
);
|
||||
compared += 1;
|
||||
}
|
||||
assert!(compared >= 40, "{compared}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user