hdf5_pure/error.rs
1//! Error types for HDF5 format parsing.
2
3#[cfg(not(feature = "std"))]
4extern crate alloc;
5
6#[cfg(not(feature = "std"))]
7use alloc::string::String;
8
9#[cfg(feature = "std")]
10use std::string::String;
11
12use core::fmt;
13
14/// Errors that can occur when parsing HDF5 binary format structures.
15#[derive(Debug, Clone, PartialEq, Eq)]
16#[non_exhaustive]
17pub enum FormatError {
18 /// The HDF5 magic signature was not found at any valid offset.
19 SignatureNotFound,
20 /// The superblock version is not supported.
21 UnsupportedVersion(u8),
22 /// Unexpected end of data.
23 UnexpectedEof {
24 /// Number of bytes expected.
25 expected: usize,
26 /// Number of bytes actually available.
27 available: usize,
28 },
29 /// Invalid offset size (must be 2, 4, or 8).
30 InvalidOffsetSize(u8),
31 /// Invalid length size (must be 2, 4, or 8).
32 InvalidLengthSize(u8),
33 /// Invalid object header signature.
34 InvalidObjectHeaderSignature,
35 /// Invalid object header version.
36 InvalidObjectHeaderVersion(u8),
37 /// Unknown message type that is marked as must-understand.
38 UnsupportedMessage(u16),
39 /// Invalid datatype class.
40 InvalidDatatypeClass(u8),
41 /// Invalid datatype version for a given class.
42 InvalidDatatypeVersion {
43 /// The type class.
44 class: u8,
45 /// The version found.
46 version: u8,
47 },
48 /// Invalid string padding type.
49 InvalidStringPadding(u8),
50 /// Invalid character set.
51 InvalidCharacterSet(u8),
52 /// Invalid byte order.
53 InvalidByteOrder(u8),
54 /// Invalid reference type.
55 InvalidReferenceType(u8),
56 /// Invalid file-space management strategy code in a File Space Info message.
57 InvalidFileSpaceStrategy(u8),
58 /// Unsupported File Space Info message version (only version 1 is handled).
59 UnsupportedFileSpaceInfoVersion(u8),
60 /// A free-space manager block (`FSHD`/`FSSE`) is malformed.
61 InvalidFreeSpaceManager,
62 /// A compound datatype has a zero total size.
63 InvalidCompoundSize,
64 /// A compound datatype contains no fields.
65 EmptyCompoundType,
66 /// A compound datatype contains the same field name more than once.
67 DuplicateCompoundField(String),
68 /// A compound field extends past the declared compound size.
69 CompoundFieldOutOfBounds {
70 /// Field name.
71 name: String,
72 /// Field byte offset.
73 offset: u64,
74 /// Field size in bytes.
75 field_size: u32,
76 /// Declared compound size in bytes.
77 compound_size: u32,
78 },
79 /// Two compound fields overlap.
80 CompoundFieldOverlap {
81 /// Earlier field in byte order.
82 first: String,
83 /// Later field in byte order.
84 second: String,
85 },
86 /// A named compound field was not present.
87 CompoundFieldMissing(String),
88 /// A compound field has an incompatible datatype.
89 CompoundFieldTypeMismatch(String),
90 /// Invalid dataspace version.
91 InvalidDataspaceVersion(u8),
92 /// Invalid dataspace type.
93 InvalidDataspaceType(u8),
94 /// Invalid data layout version.
95 InvalidLayoutVersion(u8),
96 /// Invalid data layout class.
97 InvalidLayoutClass(u8),
98 /// No data allocated for contiguous layout.
99 NoDataAllocated,
100 /// Type mismatch when reading data.
101 TypeMismatch {
102 /// Expected type description.
103 expected: &'static str,
104 /// Actual type description.
105 actual: &'static str,
106 },
107 /// Data size mismatch.
108 DataSizeMismatch {
109 /// Expected size in bytes.
110 expected: usize,
111 /// Actual size in bytes.
112 actual: usize,
113 },
114 /// Invalid local heap signature.
115 InvalidLocalHeapSignature,
116 /// Invalid local heap version.
117 InvalidLocalHeapVersion(u8),
118 /// Invalid B-tree v1 signature.
119 InvalidBTreeSignature,
120 /// Invalid B-tree node type.
121 InvalidBTreeNodeType(u8),
122 /// Invalid symbol table node signature.
123 InvalidSymbolTableNodeSignature,
124 /// Invalid symbol table node version.
125 InvalidSymbolTableNodeVersion(u8),
126 /// Path not found during group traversal.
127 PathNotFound(String),
128 /// Invalid Link message version.
129 InvalidLinkVersion(u8),
130 /// Invalid link type code.
131 InvalidLinkType(u8),
132 /// Invalid Link Info message version.
133 InvalidLinkInfoVersion(u8),
134 /// Invalid B-tree v2 signature.
135 InvalidBTreeV2Signature,
136 /// Invalid B-tree v2 version.
137 InvalidBTreeV2Version(u8),
138 /// Invalid fractal heap signature.
139 InvalidFractalHeapSignature,
140 /// Invalid fractal heap version.
141 InvalidFractalHeapVersion(u8),
142 /// Invalid heap ID type.
143 InvalidHeapIdType(u8),
144 /// A fractal-heap "huge" object's heap ID referenced a B-tree key that is
145 /// not present in the heap's huge-objects v2 B-tree.
146 HugeObjectNotFound(u64),
147 /// A fractal-heap object lives in an I/O-filter-encoded heap (filtered
148 /// managed or huge storage), whose filtered bytes this reader does not
149 /// decode. Link and attribute heaps are never filtered, so this does not
150 /// arise for them.
151 UnsupportedFilteredHeapObject,
152 /// A dataset uses the Virtual (VDS) data layout, which maps its elements to
153 /// regions of other datasets, possibly in other files. This reader does not
154 /// yet resolve virtual mappings, so such a dataset is refused rather than
155 /// read as empty or wrong.
156 UnsupportedVirtualLayout,
157 /// Invalid attribute message version.
158 InvalidAttributeVersion(u8),
159 /// Invalid Attribute Info message version.
160 InvalidAttributeInfoVersion(u8),
161 /// Invalid shared message version.
162 InvalidSharedMessageVersion(u8),
163 /// Invalid global heap collection signature.
164 InvalidGlobalHeapSignature,
165 /// Invalid global heap version.
166 InvalidGlobalHeapVersion(u8),
167 /// Global heap object not found.
168 GlobalHeapObjectNotFound {
169 /// Address of the collection.
170 collection_address: u64,
171 /// Index that was not found.
172 index: u16,
173 },
174 /// Variable-length data error.
175 VlDataError(String),
176 /// A variable-length read exceeded its configured element limit.
177 VariableLengthElementLimitExceeded {
178 /// Maximum number of elements permitted by the caller.
179 limit: usize,
180 /// Number of elements present in the selected data.
181 actual: u64,
182 },
183 /// A variable-length read exceeded its configured payload-byte limit.
184 VariableLengthByteLimitExceeded {
185 /// Maximum number of payload bytes permitted by the caller.
186 limit: usize,
187 /// Number of payload bytes required by the selected data.
188 required: u64,
189 },
190 /// Serialization error.
191 SerializationError(String),
192 /// Dataset is missing data.
193 DatasetMissingData,
194 /// Dataset is missing shape.
195 DatasetMissingShape,
196 /// A variable-length string dataset was requested with chunked, filtered,
197 /// or resizable storage. VL element references live in the global heap,
198 /// whose addresses are only known after data layout, so they cannot be
199 /// patched into compressed chunks written beforehand.
200 ChunkedVlenStringUnsupported,
201 /// The dataset's element count implied by its shape does not match the
202 /// amount of data supplied (`shape.product() * element_size != data.len()`).
203 ShapeDataMismatch {
204 /// Number of data bytes the shape requires (`product(shape) * element_size`).
205 expected: usize,
206 /// Number of data bytes actually supplied.
207 actual: usize,
208 /// Size in bytes of one element (the dataset's datatype size). Always
209 /// non-zero; used to report the mismatch in elements as well as bytes.
210 element_size: usize,
211 },
212 /// A chunked/filtered/extensible dataset's chunk geometry is invalid — for
213 /// example chunk dimensions whose rank disagrees with the shape, a zero chunk
214 /// dimension, a maximum shape whose rank disagrees with the shape or that is
215 /// smaller than the current shape, or chunking requested on a scalar dataset.
216 /// Reported up front so a malformed request is refused instead of panicking
217 /// in the chunk splitter or producing an unreadable dataset. The payload is a
218 /// human-readable reason.
219 InvalidChunkGeometry(&'static str),
220 /// Invalid filter pipeline version.
221 InvalidFilterPipelineVersion(u8),
222 /// Unsupported filter ID.
223 UnsupportedFilter(u16),
224 /// Filter processing error.
225 FilterError(String),
226 /// Decompression error.
227 DecompressionError(String),
228 /// Compression error.
229 CompressionError(String),
230 /// Fletcher32 checksum mismatch.
231 Fletcher32Mismatch {
232 /// Expected checksum.
233 expected: u32,
234 /// Computed checksum.
235 computed: u32,
236 },
237 /// Chunked dataset read error.
238 ChunkedReadError(String),
239 /// Chunk assembly error.
240 ChunkAssemblyError(String),
241 /// CRC32C checksum mismatch.
242 ChecksumMismatch {
243 /// The checksum stored in the file.
244 expected: u32,
245 /// The checksum we computed.
246 computed: u32,
247 },
248 /// Maximum nesting/continuation depth exceeded (malformed data protection).
249 NestingDepthExceeded,
250 /// Duplicate dataset name detected during parallel metadata merge.
251 DuplicateDatasetName(String),
252 /// ZFP filter configuration is invalid (e.g. missing element type, rank out of range).
253 UnsupportedZfp(String),
254 /// A file-derived 64-bit value (an offset, length, size, or element count)
255 /// does not fit in the target integer type on this platform. This is the
256 /// guard that replaces silent `as usize` / `as u32` truncation: on a 32-bit
257 /// host, `usize` is 32 bits, so an HDF5 offset or length above `usize::MAX`
258 /// would otherwise wrap and read the wrong bytes. The original value is
259 /// preserved for diagnostics, and `target` names the type we tried to
260 /// narrow to (e.g. `"usize"`, `"u32"`).
261 ValueTooLargeForPlatform {
262 /// The original 64-bit value read from the file.
263 value: u64,
264 /// The platform integer type the value could not fit into.
265 target: &'static str,
266 },
267 /// Two file-derived values (typically an offset and a length) overflow `u64`
268 /// when added to form a slice bound. Reported instead of wrapping so a
269 /// malformed file cannot produce a wrapped or out-of-range index.
270 OffsetOverflow {
271 /// First operand (typically the base offset/address).
272 offset: u64,
273 /// Second operand (typically the length/size).
274 length: u64,
275 },
276 /// A random-access byte source (see [`crate::source::FileSource`]) failed to
277 /// supply the requested bytes. The string carries a backend-specific reason
278 /// (e.g. an underlying `std::io::Error` rendered to text), so this stays
279 /// `no_std`/`alloc`-friendly and free of an `std::io` dependency.
280 Source(String),
281 /// The library-version bounds requested via
282 /// [`FileBuilder::with_libver_bounds`](crate::FileBuilder::with_libver_bounds)
283 /// cannot be satisfied. This crate's writer emits exactly one on-disk format
284 /// (the version 3 / HDF5 1.10 superblock), so a bound that excludes it — an
285 /// upper bound older than 1.10, or a lower bound newer than 1.10 — is
286 /// unsatisfiable. The fields carry the format produced and the bounds asked
287 /// for, as [`LibVer::name`](crate::LibVer::name) labels.
288 LibverBoundsUnsatisfiable {
289 /// The library-version label of the format this crate writes.
290 writes: &'static str,
291 /// The requested lower bound.
292 requested_low: &'static str,
293 /// The requested upper bound.
294 requested_high: &'static str,
295 },
296 /// An HDF5 object reference (`H5R_OBJECT`) could not be resolved to an
297 /// object: the stored address is null or undefined (`HADDR_UNDEF`), or it
298 /// does not point at a group or dataset object header. The payload is the
299 /// stored (base-relative) address, preserved for diagnostics.
300 InvalidObjectReference(u64),
301}
302
303impl fmt::Display for FormatError {
304 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
305 match self {
306 FormatError::SignatureNotFound => {
307 write!(f, "HDF5 signature not found at any valid offset")
308 }
309 FormatError::UnsupportedVersion(v) => {
310 write!(f, "unsupported superblock version: {v}")
311 }
312 FormatError::UnexpectedEof {
313 expected,
314 available,
315 } => {
316 write!(f, "unexpected EOF: need {expected} bytes, have {available}")
317 }
318 FormatError::InvalidOffsetSize(s) => {
319 write!(f, "invalid offset size: {s} (must be 2, 4, or 8)")
320 }
321 FormatError::InvalidLengthSize(s) => {
322 write!(f, "invalid length size: {s} (must be 2, 4, or 8)")
323 }
324 FormatError::InvalidObjectHeaderSignature => {
325 write!(f, "invalid object header signature")
326 }
327 FormatError::InvalidObjectHeaderVersion(v) => {
328 write!(f, "invalid object header version: {v}")
329 }
330 FormatError::UnsupportedMessage(id) => {
331 write!(
332 f,
333 "unsupported message type {id:#06x} marked as must-understand"
334 )
335 }
336 FormatError::InvalidDatatypeClass(c) => {
337 write!(f, "invalid datatype class: {c}")
338 }
339 FormatError::InvalidDatatypeVersion { class, version } => {
340 write!(f, "invalid datatype version {version} for class {class}")
341 }
342 FormatError::InvalidStringPadding(p) => {
343 write!(f, "invalid string padding type: {p}")
344 }
345 FormatError::InvalidCharacterSet(c) => {
346 write!(f, "invalid character set: {c}")
347 }
348 FormatError::InvalidByteOrder(b) => {
349 write!(f, "invalid byte order: {b}")
350 }
351 FormatError::InvalidReferenceType(r) => {
352 write!(f, "invalid reference type: {r}")
353 }
354 FormatError::InvalidFileSpaceStrategy(s) => {
355 write!(f, "invalid file-space strategy code: {s}")
356 }
357 FormatError::UnsupportedFileSpaceInfoVersion(v) => {
358 write!(f, "unsupported File Space Info message version: {v}")
359 }
360 FormatError::InvalidFreeSpaceManager => {
361 write!(f, "malformed free-space manager block (FSHD/FSSE)")
362 }
363 FormatError::InvalidCompoundSize => {
364 write!(f, "compound datatype size must be greater than zero")
365 }
366 FormatError::EmptyCompoundType => {
367 write!(f, "compound datatype must contain at least one field")
368 }
369 FormatError::DuplicateCompoundField(name) => {
370 write!(f, "duplicate compound field name: {name}")
371 }
372 FormatError::CompoundFieldOutOfBounds {
373 name,
374 offset,
375 field_size,
376 compound_size,
377 } => {
378 write!(
379 f,
380 "compound field {name:?} at offset {offset} with size {field_size} \
381 exceeds compound size {compound_size}"
382 )
383 }
384 FormatError::CompoundFieldOverlap { first, second } => {
385 write!(f, "compound fields {first:?} and {second:?} overlap")
386 }
387 FormatError::CompoundFieldMissing(name) => {
388 write!(f, "compound field {name:?} is missing")
389 }
390 FormatError::CompoundFieldTypeMismatch(name) => {
391 write!(f, "compound field {name:?} has an incompatible datatype")
392 }
393 FormatError::InvalidDataspaceVersion(v) => {
394 write!(f, "invalid dataspace version: {v}")
395 }
396 FormatError::InvalidDataspaceType(t) => {
397 write!(f, "invalid dataspace type: {t}")
398 }
399 FormatError::InvalidLayoutVersion(v) => {
400 write!(f, "invalid data layout version: {v}")
401 }
402 FormatError::InvalidLayoutClass(c) => {
403 write!(f, "invalid data layout class: {c}")
404 }
405 FormatError::NoDataAllocated => {
406 write!(f, "no data allocated for contiguous layout")
407 }
408 FormatError::TypeMismatch { expected, actual } => {
409 write!(f, "type mismatch: expected {expected}, got {actual}")
410 }
411 FormatError::DataSizeMismatch { expected, actual } => {
412 write!(
413 f,
414 "data size mismatch: expected {expected} bytes, got {actual} bytes"
415 )
416 }
417 FormatError::InvalidLocalHeapSignature => {
418 write!(f, "invalid local heap signature")
419 }
420 FormatError::InvalidLocalHeapVersion(v) => {
421 write!(f, "invalid local heap version: {v}")
422 }
423 FormatError::InvalidBTreeSignature => {
424 write!(f, "invalid B-tree v1 signature")
425 }
426 FormatError::InvalidBTreeNodeType(t) => {
427 write!(f, "invalid B-tree node type: {t}")
428 }
429 FormatError::InvalidSymbolTableNodeSignature => {
430 write!(f, "invalid symbol table node signature")
431 }
432 FormatError::InvalidSymbolTableNodeVersion(v) => {
433 write!(f, "invalid symbol table node version: {v}")
434 }
435 FormatError::PathNotFound(p) => {
436 write!(f, "path not found: {p}")
437 }
438 FormatError::InvalidLinkVersion(v) => {
439 write!(f, "invalid link message version: {v}")
440 }
441 FormatError::InvalidLinkType(t) => {
442 write!(f, "invalid link type: {t}")
443 }
444 FormatError::InvalidLinkInfoVersion(v) => {
445 write!(f, "invalid link info message version: {v}")
446 }
447 FormatError::InvalidBTreeV2Signature => {
448 write!(f, "invalid B-tree v2 signature")
449 }
450 FormatError::InvalidBTreeV2Version(v) => {
451 write!(f, "invalid B-tree v2 version: {v}")
452 }
453 FormatError::InvalidFractalHeapSignature => {
454 write!(f, "invalid fractal heap signature")
455 }
456 FormatError::InvalidFractalHeapVersion(v) => {
457 write!(f, "invalid fractal heap version: {v}")
458 }
459 FormatError::InvalidHeapIdType(t) => {
460 write!(f, "invalid heap ID type: {t}")
461 }
462 FormatError::HugeObjectNotFound(id) => {
463 write!(f, "fractal-heap huge object {id} not found in B-tree")
464 }
465 FormatError::UnsupportedFilteredHeapObject => {
466 write!(f, "filtered fractal-heap objects are not supported")
467 }
468 FormatError::UnsupportedVirtualLayout => {
469 write!(f, "virtual (VDS) data layout is not supported")
470 }
471 FormatError::InvalidAttributeVersion(v) => {
472 write!(f, "invalid attribute message version: {v}")
473 }
474 FormatError::InvalidAttributeInfoVersion(v) => {
475 write!(f, "invalid attribute info message version: {v}")
476 }
477 FormatError::InvalidSharedMessageVersion(v) => {
478 write!(f, "invalid shared message version: {v}")
479 }
480 FormatError::InvalidGlobalHeapSignature => {
481 write!(f, "invalid global heap collection signature")
482 }
483 FormatError::InvalidGlobalHeapVersion(v) => {
484 write!(f, "invalid global heap version: {v}")
485 }
486 FormatError::GlobalHeapObjectNotFound {
487 collection_address,
488 index,
489 } => {
490 write!(
491 f,
492 "global heap object not found: collection {collection_address:#x}, index {index}"
493 )
494 }
495 FormatError::VlDataError(msg) => {
496 write!(f, "variable-length data error: {msg}")
497 }
498 FormatError::VariableLengthElementLimitExceeded { limit, actual } => {
499 write!(
500 f,
501 "variable-length element limit exceeded: limit is {limit}, data contains {actual}"
502 )
503 }
504 FormatError::VariableLengthByteLimitExceeded { limit, required } => {
505 write!(
506 f,
507 "variable-length payload limit exceeded: limit is {limit} bytes, \
508 data requires {required} bytes"
509 )
510 }
511 FormatError::SerializationError(msg) => {
512 write!(f, "serialization error: {msg}")
513 }
514 FormatError::DatasetMissingData => {
515 write!(f, "dataset is missing data")
516 }
517 FormatError::DatasetMissingShape => {
518 write!(f, "dataset is missing shape")
519 }
520 FormatError::ChunkedVlenStringUnsupported => {
521 write!(
522 f,
523 "chunked, filtered, or resizable variable-length string datasets cannot be written"
524 )
525 }
526 FormatError::ShapeDataMismatch {
527 expected,
528 actual,
529 element_size,
530 } => {
531 // `element_size` is guaranteed non-zero at construction, so the
532 // element counts below are well defined.
533 write!(
534 f,
535 "shape/data mismatch: shape requires {} elements ({expected} bytes), \
536 but {} elements ({actual} bytes) were supplied",
537 expected / element_size,
538 actual / element_size,
539 )
540 }
541 FormatError::InvalidChunkGeometry(reason) => {
542 write!(f, "invalid chunk geometry: {reason}")
543 }
544 FormatError::InvalidFilterPipelineVersion(v) => {
545 write!(f, "invalid filter pipeline version: {v}")
546 }
547 FormatError::UnsupportedFilter(id) => {
548 write!(f, "unsupported filter: {id}")
549 }
550 FormatError::FilterError(msg) => {
551 write!(f, "filter error: {msg}")
552 }
553 FormatError::DecompressionError(msg) => {
554 write!(f, "decompression error: {msg}")
555 }
556 FormatError::CompressionError(msg) => {
557 write!(f, "compression error: {msg}")
558 }
559 FormatError::Fletcher32Mismatch { expected, computed } => {
560 write!(
561 f,
562 "fletcher32 mismatch: expected {expected:#010x}, computed {computed:#010x}"
563 )
564 }
565 FormatError::ChunkedReadError(msg) => {
566 write!(f, "chunked read error: {msg}")
567 }
568 FormatError::ChunkAssemblyError(msg) => {
569 write!(f, "chunk assembly error: {msg}")
570 }
571 FormatError::ChecksumMismatch { expected, computed } => {
572 write!(
573 f,
574 "checksum mismatch: expected {expected:#010x}, computed {computed:#010x}"
575 )
576 }
577 FormatError::NestingDepthExceeded => {
578 write!(f, "maximum nesting/continuation depth exceeded")
579 }
580 FormatError::DuplicateDatasetName(name) => {
581 write!(f, "duplicate dataset name during parallel merge: {name}")
582 }
583 FormatError::UnsupportedZfp(msg) => {
584 write!(f, "unsupported ZFP configuration: {msg}")
585 }
586 FormatError::ValueTooLargeForPlatform { value, target } => {
587 write!(
588 f,
589 "file value {value} does not fit in {target} on this platform \
590 (a 64-bit HDF5 offset/length exceeds this target's address width)"
591 )
592 }
593 FormatError::OffsetOverflow { offset, length } => {
594 write!(
595 f,
596 "offset arithmetic overflow: {offset} + {length} exceeds u64"
597 )
598 }
599 FormatError::Source(msg) => {
600 write!(f, "byte source error: {msg}")
601 }
602 FormatError::LibverBoundsUnsatisfiable {
603 writes,
604 requested_low,
605 requested_high,
606 } => {
607 write!(
608 f,
609 "requested library-version bounds [{requested_low}, {requested_high}] \
610 cannot be satisfied: this crate writes the {writes} format"
611 )
612 }
613 FormatError::InvalidObjectReference(addr) => {
614 write!(
615 f,
616 "invalid HDF5 object reference: address {addr:#x} is null/undefined \
617 or does not point at a group or dataset"
618 )
619 }
620 }
621 }
622}
623
624#[cfg(feature = "std")]
625impl std::error::Error for FormatError {}
626
627// ---------------------------------------------------------------------------
628// High-level Error type
629// ---------------------------------------------------------------------------
630
631/// Errors that can occur when using the high-level API.
632#[cfg(feature = "std")]
633#[derive(Debug)]
634#[non_exhaustive]
635pub enum Error {
636 /// I/O error from the filesystem.
637 Io(std::io::Error),
638 /// Low-level format parsing error.
639 Format(FormatError),
640 /// The object at the given path is not a dataset.
641 NotADataset(String),
642 /// A required header message was not found.
643 MissingMessage(crate::message_type::MessageType),
644 /// Alignment or size error for zero-copy typed access.
645 AlignmentError(String),
646 /// An array shape error from the `ndarray` integration: either the flat
647 /// data could not be reshaped to the dataset's dimensions, or a requested
648 /// static rank (e.g. `read_array::<_, Ix2>`) did not match the dataset's
649 /// runtime rank. Only constructed when the `ndarray` feature is enabled.
650 Shape(String),
651 /// A SWMR operation (e.g. [`crate::File::refresh`]) was requested on a file
652 /// that was not opened for SWMR reading via `File::open_swmr`.
653 SwmrUnsupported,
654 /// The file or dataset is not a supported target for the SWMR append writer
655 /// (e.g. a userblock or non-latest-format file, or a dataset that is
656 /// filtered, not rank-1 with an unlimited dimension, or not
657 /// Extensible-Array indexed). The payload is a human-readable reason.
658 SwmrAppendUnsupported(&'static str),
659 /// The file or the requested object is not a supported target for the
660 /// in-place editor ([`crate::EditSession`]) — for example a userblock or
661 /// non-latest-format file, a group whose links are densely stored, or a
662 /// dataset shape/datatype/filter combination the in-place writer cannot
663 /// emit yet. The payload is a human-readable reason.
664 EditUnsupported(&'static str),
665 /// An object in the source file cannot be reproduced faithfully by
666 /// [`repack`](crate::repack), so the repack was refused rather than write a
667 /// silently degraded file — for example a variable-length, time, bitfield,
668 /// or opaque datatype, a virtual/external data layout, an unsupported
669 /// filter, or an object reference. The payload names the object and reason.
670 RepackUnsupported(String),
671 /// The file could not be opened because another process holds a conflicting
672 /// OS advisory lock — for a writer ([`crate::SwmrWriter`],
673 /// [`crate::EditSession`]) this means another writer or reader is active;
674 /// for a plain reader it means a writer is active. The lock is released
675 /// automatically when the holder's process exits, so a crashed writer does
676 /// not leave a stale lock. Locking can be disabled per open with
677 /// [`crate::FileLocking::Disabled`] or globally with
678 /// `HDF5_USE_FILE_LOCKING=FALSE`. The payload is a human-readable reason.
679 FileLocked(String),
680}
681
682#[cfg(feature = "std")]
683impl fmt::Display for Error {
684 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
685 match self {
686 Error::Io(e) => write!(f, "I/O error: {e}"),
687 Error::Format(e) => write!(f, "HDF5 format error: {e}"),
688 Error::NotADataset(path) => write!(f, "not a dataset: {path}"),
689 Error::MissingMessage(mt) => write!(f, "missing required message: {mt:?}"),
690 Error::AlignmentError(msg) => write!(f, "alignment error: {msg}"),
691 Error::Shape(msg) => write!(f, "array shape error: {msg}"),
692 Error::SwmrUnsupported => write!(
693 f,
694 "refresh requires a file opened with File::open_swmr (live handle)"
695 ),
696 Error::SwmrAppendUnsupported(reason) => {
697 write!(f, "unsupported SWMR append target: {reason}")
698 }
699 Error::EditUnsupported(reason) => {
700 write!(f, "unsupported in-place edit target: {reason}")
701 }
702 Error::RepackUnsupported(reason) => {
703 write!(f, "cannot repack faithfully: {reason}")
704 }
705 Error::FileLocked(reason) => write!(f, "file is locked: {reason}"),
706 }
707 }
708}
709
710#[cfg(feature = "std")]
711impl std::error::Error for Error {
712 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
713 match self {
714 Error::Io(e) => Some(e),
715 Error::Format(e) => Some(e),
716 _ => None,
717 }
718 }
719}
720
721#[cfg(feature = "std")]
722impl From<FormatError> for Error {
723 fn from(e: FormatError) -> Self {
724 Error::Format(e)
725 }
726}
727
728#[cfg(feature = "std")]
729impl From<std::io::Error> for Error {
730 fn from(e: std::io::Error) -> Self {
731 Error::Io(e)
732 }
733}