Range reads M0/M1 (indexed lookups, Storage trait), ZFP, in-place editing #17
@@ -7,6 +7,7 @@ use alloc::{format, string::String, vec::Vec};
|
||||
use std::string::String;
|
||||
|
||||
use crate::error::FormatError;
|
||||
use crate::storage::Storage;
|
||||
|
||||
/// A single VDS (Virtual Dataset) source mapping.
|
||||
///
|
||||
@@ -309,6 +310,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(
|
||||
&mut self,
|
||||
file_data: &dyn Storage,
|
||||
length_size: u8,
|
||||
) -> Result<(), FormatError> {
|
||||
if let DataLayout::Virtual {
|
||||
global_heap_address,
|
||||
@@ -318,11 +329,8 @@ impl DataLayout {
|
||||
} = self
|
||||
&& let Some(addr) = *global_heap_address
|
||||
{
|
||||
let coll = crate::global_heap::GlobalHeapCollection::parse(
|
||||
file_data,
|
||||
addr as usize,
|
||||
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,
|
||||
@@ -1305,4 +1313,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