//! Error types for HDF5 format parsing. #[cfg(not(feature = "std"))] extern crate alloc; #[cfg(not(feature = "std"))] use alloc::string::String; #[cfg(feature = "std")] use std::string::String; use core::fmt; /// Errors that can occur when parsing HDF5 binary format structures. #[derive(Debug, Clone, PartialEq, Eq)] pub enum FormatError { /// The HDF5 magic signature was not found at any valid offset. SignatureNotFound, /// The superblock version is not supported. UnsupportedVersion(u8), /// Unexpected end of data. UnexpectedEof { /// Number of bytes expected. expected: usize, /// Number of bytes actually available. available: usize, }, /// Invalid offset size (must be 2, 4, or 8). InvalidOffsetSize(u8), /// Invalid length size (must be 2, 4, or 8). InvalidLengthSize(u8), /// Invalid object header signature. InvalidObjectHeaderSignature, /// Invalid object header version. InvalidObjectHeaderVersion(u8), /// Unknown message type that is marked as must-understand. UnsupportedMessage(u16), /// Invalid datatype class. InvalidDatatypeClass(u8), /// Invalid datatype version for a given class. InvalidDatatypeVersion { /// The type class. class: u8, /// The version found. version: u8, }, /// Invalid string padding type. InvalidStringPadding(u8), /// Invalid character set. InvalidCharacterSet(u8), /// Invalid byte order. InvalidByteOrder(u8), /// Invalid reference type. InvalidReferenceType(u8), /// Invalid dataspace version. InvalidDataspaceVersion(u8), /// Invalid dataspace type. InvalidDataspaceType(u8), /// Invalid data layout version. InvalidLayoutVersion(u8), /// Invalid data layout class. InvalidLayoutClass(u8), /// No data allocated for contiguous layout. NoDataAllocated, /// Type mismatch when reading data. TypeMismatch { /// Expected type description. expected: &'static str, /// Actual type description. actual: &'static str, }, /// Data size mismatch. DataSizeMismatch { /// Expected size in bytes. expected: usize, /// Actual size in bytes. actual: usize, }, /// Invalid local heap signature. InvalidLocalHeapSignature, /// Invalid local heap version. InvalidLocalHeapVersion(u8), /// A local heap's free list points outside its data segment (libhdf5: /// "bad heap free list"). InvalidLocalHeapFreeList, /// Invalid B-tree v1 signature. InvalidBTreeSignature, /// Invalid B-tree node type. InvalidBTreeNodeType(u8), /// Invalid symbol table node signature. InvalidSymbolTableNodeSignature, /// Invalid symbol table node version. InvalidSymbolTableNodeVersion(u8), /// Path not found during group traversal. PathNotFound(String), /// Invalid Link message version. InvalidLinkVersion(u8), /// Invalid link type code. InvalidLinkType(u8), /// Invalid Link Info message version. InvalidLinkInfoVersion(u8), /// Invalid Group Info message version. InvalidGroupInfoVersion(u8), /// Invalid B-tree v2 signature. InvalidBTreeV2Signature, /// Invalid B-tree v2 version. InvalidBTreeV2Version(u8), /// Invalid fractal heap signature. InvalidFractalHeapSignature, /// Invalid fractal heap version. InvalidFractalHeapVersion(u8), /// Invalid heap ID type. InvalidHeapIdType(u8), /// Invalid attribute message version. InvalidAttributeVersion(u8), /// Invalid Attribute Info message version. InvalidAttributeInfoVersion(u8), /// Invalid shared message version. InvalidSharedMessageVersion(u8), /// A message is marked shared but was parsed without access to the file, /// so the reference to the real message could not be followed. UnresolvedSharedMessage, /// A shared-message reference points at an object header that holds no /// (unshared) message of the referenced type (raw message type id). SharedMessageTargetMissing(u16), /// A superblock was parsed at a non-zero offset of the buffer (the file /// has a user block of this many bytes). HDF5 addresses are relative to /// the superblock, so the buffer must start there: see /// `signature::split_user_block`. UserBlockNotStripped(u64), /// A selection does not fit the dataset it was applied to (wrong rank, or /// it reaches past a dimension's extent). SelectionOutOfBounds(String), /// The dataset's raw data is stored in external files (External Data /// Files message), which this reader does not follow. ExternalDataFilesUnsupported, /// The path goes through an external link (a link into another file), /// which this reader does not follow. ExternalLinkUnsupported { /// The file the link points into. filename: String, /// The object path within that file. object_path: String, }, /// Invalid SOHM table version. InvalidSohmTableVersion(u8), /// Invalid SOHM table signature (expected "SMTB"). InvalidSohmTableSignature, /// Invalid SOHM list signature (expected "SMLI"). InvalidSohmListSignature, /// Invalid global heap collection signature. InvalidGlobalHeapSignature, /// Invalid global heap version. InvalidGlobalHeapVersion(u8), /// Global heap object not found. GlobalHeapObjectNotFound { /// Address of the collection. collection_address: u64, /// Index that was not found. index: u16, }, /// Variable-length data error. VlDataError(String), /// Serialization error. SerializationError(String), /// Dataset is missing data. DatasetMissingData, /// Dataset is missing shape. DatasetMissingShape, /// Invalid filter pipeline version. InvalidFilterPipelineVersion(u8), /// Unsupported filter ID. UnsupportedFilter(u16), /// Filter processing error. FilterError(String), /// Decompression error. DecompressionError(String), /// Compression error. CompressionError(String), /// Fletcher32 checksum mismatch. Fletcher32Mismatch { /// Expected checksum. expected: u32, /// Computed checksum. computed: u32, }, /// Chunked dataset read error. ChunkedReadError(String), /// Chunk assembly error. ChunkAssemblyError(String), /// CRC32C checksum mismatch. ChecksumMismatch { /// The checksum stored in the file. expected: u32, /// The checksum we computed. computed: u32, }, /// Maximum nesting/continuation depth exceeded (malformed data protection). NestingDepthExceeded, /// Duplicate dataset name detected during parallel metadata merge. DuplicateDatasetName(String), /// Integer overflow in size computation (malformed data protection). Overflow(String), /// An object header that libhdf5 refuses to load (the reason is /// libhdf5's own error text): a misaligned or overrunning message, a /// wrong message count, contradictory message flags, a message of a /// class that cannot be shared flagged shareable, … InvalidObjectHeader(&'static str), /// A datatype message libhdf5 refuses to decode (the reason is /// libhdf5's own error text): size 0, bit fields outside the type, /// an empty enum name, a compound member outside its compound, … InvalidDatatype(String), /// A chunked layout whose chunk dimensions libhdf5 refuses: a zero /// dimension, a rank that does not match the dataspace, an element size /// that is not the datatype's, or a chunk of 4 GiB or more indexed by a /// version-1 B-tree. InvalidChunkDimensions(String), /// The superblock's end-of-file address lies past the end of the file: /// the file was truncated (libhdf5 refuses to open it). TruncatedFile { /// End of file recorded in the superblock (relative to byte 0). stored_eof: u64, /// The file's actual length in bytes. actual_len: u64, }, } impl fmt::Display for FormatError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { FormatError::SignatureNotFound => { write!(f, "HDF5 signature not found at any valid offset") } FormatError::UnsupportedVersion(v) => { write!(f, "unsupported superblock version: {v}") } FormatError::UnexpectedEof { expected, available, } => { write!(f, "unexpected EOF: need {expected} bytes, have {available}") } FormatError::InvalidOffsetSize(s) => { write!(f, "invalid offset size: {s} (must be 2, 4, or 8)") } FormatError::InvalidLengthSize(s) => { write!(f, "invalid length size: {s} (must be 2, 4, or 8)") } FormatError::InvalidObjectHeaderSignature => { write!(f, "invalid object header signature") } FormatError::InvalidObjectHeaderVersion(v) => { write!(f, "invalid object header version: {v}") } FormatError::UnsupportedMessage(id) => { write!( f, "unsupported message type {id:#06x} marked as must-understand" ) } FormatError::InvalidDatatypeClass(c) => { write!(f, "invalid datatype class: {c}") } FormatError::InvalidDatatypeVersion { class, version } => { write!(f, "invalid datatype version {version} for class {class}") } FormatError::InvalidStringPadding(p) => { write!(f, "invalid string padding type: {p}") } FormatError::InvalidCharacterSet(c) => { write!(f, "invalid character set: {c}") } FormatError::InvalidByteOrder(b) => { write!(f, "invalid byte order: {b}") } FormatError::InvalidReferenceType(r) => { write!(f, "invalid reference type: {r}") } FormatError::InvalidDataspaceVersion(v) => { write!(f, "invalid dataspace version: {v}") } FormatError::InvalidDataspaceType(t) => { write!(f, "invalid dataspace type: {t}") } FormatError::InvalidLayoutVersion(v) => { write!(f, "invalid data layout version: {v}") } FormatError::InvalidLayoutClass(c) => { write!(f, "invalid data layout class: {c}") } FormatError::NoDataAllocated => { write!(f, "no data allocated for contiguous layout") } FormatError::TypeMismatch { expected, actual } => { write!(f, "type mismatch: expected {expected}, got {actual}") } FormatError::DataSizeMismatch { expected, actual } => { write!( f, "data size mismatch: expected {expected} bytes, got {actual} bytes" ) } FormatError::InvalidLocalHeapSignature => { write!(f, "invalid local heap signature") } FormatError::InvalidLocalHeapFreeList => { write!(f, "bad local heap free list") } FormatError::InvalidLocalHeapVersion(v) => { write!(f, "invalid local heap version: {v}") } FormatError::InvalidBTreeSignature => { write!(f, "invalid B-tree v1 signature") } FormatError::InvalidBTreeNodeType(t) => { write!(f, "invalid B-tree node type: {t}") } FormatError::InvalidSymbolTableNodeSignature => { write!(f, "invalid symbol table node signature") } FormatError::InvalidSymbolTableNodeVersion(v) => { write!(f, "invalid symbol table node version: {v}") } FormatError::PathNotFound(p) => { write!(f, "path not found: {p}") } FormatError::InvalidLinkVersion(v) => { write!(f, "invalid link message version: {v}") } FormatError::InvalidLinkType(t) => { write!(f, "invalid link type: {t}") } FormatError::InvalidLinkInfoVersion(v) => { write!(f, "invalid link info message version: {v}") } FormatError::InvalidGroupInfoVersion(v) => { write!(f, "invalid group info message version: {v}") } FormatError::InvalidBTreeV2Signature => { write!(f, "invalid B-tree v2 signature") } FormatError::InvalidBTreeV2Version(v) => { write!(f, "invalid B-tree v2 version: {v}") } FormatError::InvalidFractalHeapSignature => { write!(f, "invalid fractal heap signature") } FormatError::InvalidFractalHeapVersion(v) => { write!(f, "invalid fractal heap version: {v}") } FormatError::InvalidHeapIdType(t) => { write!(f, "invalid heap ID type: {t}") } FormatError::InvalidAttributeVersion(v) => { write!(f, "invalid attribute message version: {v}") } FormatError::InvalidAttributeInfoVersion(v) => { write!(f, "invalid attribute info message version: {v}") } FormatError::InvalidSharedMessageVersion(v) => { write!(f, "invalid shared message version: {v}") } FormatError::ExternalLinkUnsupported { filename, object_path, } => write!( f, "path goes through an external link to {object_path} in {filename}, which is \ not supported" ), FormatError::ExternalDataFilesUnsupported => write!( f, "dataset raw data is stored in external file(s), which is not supported" ), FormatError::SelectionOutOfBounds(msg) => { write!(f, "selection out of bounds: {msg}") } FormatError::UserBlockNotStripped(n) => write!( f, "file has a {n}-byte user block: parse the bytes from the superblock on \ (signature::split_user_block)" ), FormatError::SharedMessageTargetMissing(t) => write!( f, "shared message reference points at an object header with no message of type \ {t:#06x}" ), FormatError::UnresolvedSharedMessage => write!( f, "message is shared but no file data was available to resolve it" ), FormatError::InvalidSohmTableVersion(v) => { write!(f, "invalid SOHM table version: {v}") } FormatError::InvalidSohmTableSignature => { write!(f, "invalid SOHM table signature (expected SMTB)") } FormatError::InvalidSohmListSignature => { write!(f, "invalid SOHM list signature (expected SMLI)") } FormatError::InvalidGlobalHeapSignature => { write!(f, "invalid global heap collection signature") } FormatError::InvalidGlobalHeapVersion(v) => { write!(f, "invalid global heap version: {v}") } FormatError::GlobalHeapObjectNotFound { collection_address, index, } => { write!( f, "global heap object not found: collection {collection_address:#x}, index {index}" ) } FormatError::VlDataError(msg) => { write!(f, "variable-length data error: {msg}") } FormatError::SerializationError(msg) => { write!(f, "serialization error: {msg}") } FormatError::DatasetMissingData => { write!(f, "dataset is missing data") } FormatError::DatasetMissingShape => { write!(f, "dataset is missing shape") } FormatError::InvalidFilterPipelineVersion(v) => { write!(f, "invalid filter pipeline version: {v}") } FormatError::UnsupportedFilter(id) => match crate::filter_registry::known_filter(*id) { Some((name, Some(feature))) => write!( f, "unsupported filter: {id} ({name}; this build lacks the `{feature}` feature)" ), Some((name, None)) => write!( f, "unsupported filter: {id} ({name}, not implemented by clawhdf5)" ), None => write!(f, "unsupported filter: {id}"), }, FormatError::FilterError(msg) => { write!(f, "filter error: {msg}") } FormatError::DecompressionError(msg) => { write!(f, "decompression error: {msg}") } FormatError::CompressionError(msg) => { write!(f, "compression error: {msg}") } FormatError::Fletcher32Mismatch { expected, computed } => { write!( f, "fletcher32 mismatch: expected {expected:#010x}, computed {computed:#010x}" ) } FormatError::ChunkedReadError(msg) => { write!(f, "chunked read error: {msg}") } FormatError::ChunkAssemblyError(msg) => { write!(f, "chunk assembly error: {msg}") } FormatError::ChecksumMismatch { expected, computed } => { write!( f, "checksum mismatch: expected {expected:#010x}, computed {computed:#010x}" ) } FormatError::NestingDepthExceeded => { write!(f, "maximum nesting/continuation depth exceeded") } FormatError::DuplicateDatasetName(name) => { write!(f, "duplicate dataset name during parallel merge: {name}") } FormatError::Overflow(msg) => { write!(f, "integer overflow: {msg}") } FormatError::InvalidObjectHeader(why) => { write!(f, "corrupt object header: {why}") } FormatError::InvalidDatatype(why) => { write!(f, "invalid datatype: {why}") } FormatError::InvalidChunkDimensions(why) => { write!(f, "invalid chunk dimensions: {why}") } FormatError::TruncatedFile { stored_eof, actual_len, } => { write!( f, "truncated file: the superblock records end of file {stored_eof}, \ but the file is {actual_len} bytes" ) } } } } #[cfg(feature = "std")] impl std::error::Error for FormatError {}