Merge branch 'feat/p3-storage-trait' into feat/p3-range-zfp-edit
# Conflicts: # CHANGELOG.md # crates/clawhdf5-format/src/attribute.rs # crates/clawhdf5-format/src/btree_v1.rs # crates/clawhdf5-format/src/data_layout.rs # crates/clawhdf5-format/src/extensible_array.rs # crates/clawhdf5-format/src/fixed_array.rs # crates/clawhdf5-format/src/fractal_heap.rs # crates/clawhdf5-format/src/local_heap.rs # crates/clawhdf5-format/src/shared_message.rs
This commit is contained in:
@@ -8,6 +8,7 @@ use std::string::String;
|
||||
|
||||
use crate::addr::to_usize;
|
||||
use crate::error::FormatError;
|
||||
use crate::storage::Storage;
|
||||
|
||||
/// A single VDS (Virtual Dataset) source mapping.
|
||||
///
|
||||
@@ -310,6 +311,16 @@ impl DataLayout {
|
||||
&mut self,
|
||||
file_data: &[u8],
|
||||
length_size: u8,
|
||||
) -> Result<(), FormatError> {
|
||||
self.resolve_vds_mappings_in(file_data, length_size)
|
||||
}
|
||||
|
||||
/// [`Self::resolve_vds_mappings`] over any [`Storage`]: one read of the
|
||||
/// global heap collection holding the mappings.
|
||||
pub fn resolve_vds_mappings_in<S: Storage + ?Sized>(
|
||||
&mut self,
|
||||
file_data: &S,
|
||||
length_size: u8,
|
||||
) -> Result<(), FormatError> {
|
||||
if let DataLayout::Virtual {
|
||||
global_heap_address,
|
||||
@@ -319,11 +330,8 @@ impl DataLayout {
|
||||
} = self
|
||||
&& let Some(addr) = *global_heap_address
|
||||
{
|
||||
let coll = crate::global_heap::GlobalHeapCollection::parse(
|
||||
file_data,
|
||||
to_usize(addr)?,
|
||||
length_size,
|
||||
)?;
|
||||
let coll =
|
||||
crate::global_heap::GlobalHeapCollection::parse_in(file_data, addr, length_size)?;
|
||||
let obj = coll.get_object(*global_heap_index as u16).ok_or(
|
||||
FormatError::GlobalHeapObjectNotFound {
|
||||
collection_address: addr,
|
||||
@@ -1306,4 +1314,44 @@ mod tests {
|
||||
let blob = [0x01u8, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
assert!(parse_vds_mappings(&blob, 8).unwrap().is_empty());
|
||||
}
|
||||
|
||||
/// A virtual dataset's mappings resolve identically through a
|
||||
/// read_at-only CountingStorage, in two reads of the global heap.
|
||||
#[test]
|
||||
fn vds_mappings_through_storage_match_slice() {
|
||||
use crate::message_type::MessageType;
|
||||
use crate::object_header::ObjectHeader;
|
||||
use crate::storage::CountingStorage;
|
||||
let file: &[u8] = include_bytes!("../tests/fixtures/vds_same_file.h5");
|
||||
let sb = crate::superblock::Superblock::parse(file, 0).unwrap();
|
||||
let (os, ls) = (sb.offset_size, sb.length_size);
|
||||
let storage = CountingStorage::new(file.to_vec());
|
||||
let mut virtuals = 0;
|
||||
for child in
|
||||
crate::group_v2::resolve_group_children(file, &sb, sb.root_group_address).unwrap()
|
||||
{
|
||||
let h =
|
||||
ObjectHeader::parse(file, child.object_header_address as usize, os, ls).unwrap();
|
||||
let Some(msg) = h
|
||||
.messages
|
||||
.iter()
|
||||
.find(|m| m.msg_type == MessageType::DataLayout)
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
let mut want = DataLayout::parse(&msg.data, os, ls).unwrap();
|
||||
if !matches!(want, DataLayout::Virtual { .. }) {
|
||||
continue;
|
||||
}
|
||||
let mut got = want.clone();
|
||||
want.resolve_vds_mappings(file, ls).unwrap();
|
||||
storage.reset();
|
||||
got.resolve_vds_mappings_in(&storage, ls).unwrap();
|
||||
assert_eq!(format!("{got:?}"), format!("{want:?}"));
|
||||
assert!(matches!(&got, DataLayout::Virtual { mappings, .. } if !mappings.is_empty()));
|
||||
assert_eq!(storage.reads(), 2);
|
||||
virtuals += 1;
|
||||
}
|
||||
assert!(virtuals >= 1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user