wsi_streamer/
error.rs

1use thiserror::Error;
2
3/// I/O errors that can occur when reading from remote storage
4#[derive(Debug, Clone, Error)]
5pub enum IoError {
6    /// Error from S3 or S3-compatible storage
7    #[error("S3 error: {0}")]
8    S3(String),
9
10    /// Requested range exceeds resource bounds
11    #[error("Range out of bounds: requested {requested} bytes at offset {offset}, size is {size}")]
12    RangeOutOfBounds {
13        offset: u64,
14        requested: u64,
15        size: u64,
16    },
17
18    /// Network or connection error
19    #[error("Connection error: {0}")]
20    Connection(String),
21
22    /// Object not found
23    #[error("Object not found: {0}")]
24    NotFound(String),
25}
26
27/// Errors related to format detection and validation
28#[derive(Debug, Clone, Error)]
29pub enum FormatError {
30    /// I/O error while reading the file
31    #[error("I/O error: {0}")]
32    Io(#[from] IoError),
33
34    /// TIFF parsing error
35    #[error("TIFF error: {0}")]
36    Tiff(#[from] TiffError),
37
38    /// File format is not supported (should map to HTTP 415)
39    #[error("Unsupported format: {reason}")]
40    UnsupportedFormat { reason: String },
41}
42
43/// Errors that can occur when parsing TIFF files
44#[derive(Debug, Clone, Error)]
45pub enum TiffError {
46    /// I/O error while reading the file
47    #[error("I/O error: {0}")]
48    Io(#[from] IoError),
49
50    /// Invalid TIFF magic bytes (not II or MM)
51    #[error("Invalid TIFF magic bytes: expected 0x4949 (II) or 0x4D4D (MM), got 0x{0:04X}")]
52    InvalidMagic(u16),
53
54    /// Invalid TIFF version number
55    #[error("Invalid TIFF version: expected 42 (TIFF) or 43 (BigTIFF), got {0}")]
56    InvalidVersion(u16),
57
58    /// Invalid BigTIFF offset byte size (must be 8)
59    #[error("Invalid BigTIFF offset byte size: expected 8, got {0}")]
60    InvalidBigTiffOffsetSize(u16),
61
62    /// File is too small to contain a valid TIFF header
63    #[error("File too small: need at least {required} bytes, got {actual}")]
64    FileTooSmall { required: u64, actual: u64 },
65
66    /// Invalid IFD offset (points outside file or to invalid location)
67    #[error("Invalid IFD offset: {0}")]
68    InvalidIfdOffset(u64),
69
70    /// Required tag is missing from IFD
71    #[error("Missing required tag: {0}")]
72    MissingTag(&'static str),
73
74    /// Tag has unexpected type or count
75    #[error("Invalid tag value for {tag}: {message}")]
76    InvalidTagValue { tag: &'static str, message: String },
77
78    /// Unsupported compression scheme
79    #[error("Unsupported compression: {0} (only JPEG and JPEG 2000 are supported)")]
80    UnsupportedCompression(String),
81
82    /// File uses strips instead of tiles
83    #[error("Unsupported organization: file uses strips instead of tiles")]
84    StripOrganization,
85
86    /// Unknown field type in IFD entry
87    #[error("Unknown field type: {0}")]
88    UnknownFieldType(u16),
89}
90
91/// Errors that can occur when processing tiles
92#[derive(Debug, Clone, Error)]
93pub enum TileError {
94    /// I/O error while reading tile data
95    #[error("I/O error: {0}")]
96    Io(#[from] IoError),
97
98    /// TIFF/slide parsing error
99    #[error("Slide error: {0}")]
100    Slide(#[from] TiffError),
101
102    /// Error decoding source JPEG
103    #[error("Failed to decode JPEG: {message}")]
104    DecodeError { message: String },
105
106    /// Error encoding output JPEG
107    #[error("Failed to encode JPEG: {message}")]
108    EncodeError { message: String },
109
110    /// Requested pyramid level does not exist
111    #[error("Invalid level: {level} (slide has {max_levels} levels)")]
112    InvalidLevel { level: usize, max_levels: usize },
113
114    /// Requested tile coordinates are out of bounds
115    #[error("Tile coordinates out of bounds: ({x}, {y}) at level {level} (max: {max_x}, {max_y})")]
116    TileOutOfBounds {
117        level: usize,
118        x: u32,
119        y: u32,
120        max_x: u32,
121        max_y: u32,
122    },
123
124    /// Slide not found
125    #[error("Slide not found: {slide_id}")]
126    SlideNotFound { slide_id: String },
127
128    /// Invalid quality parameter
129    #[error("Invalid quality: {quality} (must be 1-100)")]
130    InvalidQuality { quality: u8 },
131}