Skip to main content

tiff_reader/
error.rs

1use thiserror::Error;
2use tiff_core::{Compression, LayoutError};
3
4pub type Result<T> = std::result::Result<T, Error>;
5
6#[derive(Debug, Error)]
7pub enum Error {
8    #[error("I/O error reading {1}: {0}")]
9    Io(#[source] std::io::Error, String),
10
11    #[error("not a TIFF file: invalid magic bytes")]
12    InvalidMagic,
13
14    #[error("unsupported TIFF version: {0}")]
15    UnsupportedVersion(u16),
16
17    #[error("invalid BigTIFF header: {0}")]
18    InvalidBigTiffHeader(String),
19
20    #[error("IFD index {0} not found")]
21    IfdNotFound(usize),
22
23    #[error("tag {0} not found in IFD")]
24    TagNotFound(u16),
25
26    #[error("unexpected tag type {actual} for tag {tag}, expected {expected}")]
27    UnexpectedTagType {
28        tag: u16,
29        expected: &'static str,
30        actual: u16,
31    },
32
33    #[error(
34        "unsupported compression: {name} ({0})",
35        name = unsupported_compression_name(*.0)
36    )]
37    UnsupportedCompression(u16),
38
39    #[error("unsupported predictor: {0}")]
40    UnsupportedPredictor(u16),
41
42    #[error("unsupported planar configuration: {0}")]
43    UnsupportedPlanarConfiguration(u16),
44
45    #[error("unsupported bits per sample: {0}")]
46    UnsupportedBitsPerSample(u16),
47
48    #[error("unsupported sample format: {0}")]
49    UnsupportedSampleFormat(u16),
50
51    #[error("decompression failed for strip/tile {index}: {reason}")]
52    DecompressionFailed { index: usize, reason: String },
53
54    #[error("decoded output byte length {requested} exceeds decode output budget {limit}")]
55    DecodeOutputTooLarge { requested: usize, limit: usize },
56
57    #[error("failed to allocate {requested} decoded output bytes: {reason}")]
58    DecodeOutputAllocationFailed { requested: usize, reason: String },
59
60    #[error("data truncated at offset {offset}: need {needed} bytes, have {available}")]
61    Truncated {
62        offset: u64,
63        needed: u64,
64        available: u64,
65    },
66
67    #[error("offset {offset} with length {length} is out of bounds for a {data_len}-byte file")]
68    OffsetOutOfBounds {
69        offset: u64,
70        length: u64,
71        data_len: u64,
72    },
73
74    #[error("invalid TIFF tag {tag}: {reason}")]
75    InvalidTagValue { tag: u16, reason: String },
76
77    #[error("invalid image layout: {0}")]
78    InvalidImageLayout(String),
79
80    #[error("type mismatch: expected {expected}, found {actual}")]
81    TypeMismatch {
82        expected: &'static str,
83        actual: String,
84    },
85
86    #[error("band index {index} is out of bounds for {band_count} bands")]
87    BandIndexOutOfBounds { index: usize, band_count: usize },
88
89    #[error("{0}")]
90    Other(String),
91}
92
93impl From<LayoutError> for Error {
94    fn from(error: LayoutError) -> Self {
95        Self::InvalidImageLayout(error.to_string())
96    }
97}
98
99fn unsupported_compression_name(code: u16) -> &'static str {
100    Compression::from_code(code)
101        .map(Compression::name)
102        .unwrap_or("unknown")
103}