Skip to main content

oxigdal_vrt/
error.rs

1//! Error types for VRT operations
2
3use oxigdal_core::error::OxiGdalError;
4use thiserror::Error;
5
6/// Result type for VRT operations
7pub type Result<T> = core::result::Result<T, VrtError>;
8
9/// VRT-specific error types
10#[derive(Debug, Error)]
11pub enum VrtError {
12    /// XML parsing error
13    #[error("XML parsing error: {message}")]
14    XmlParse {
15        /// Error message
16        message: String,
17    },
18
19    /// Invalid VRT structure
20    #[error("Invalid VRT structure: {message}")]
21    InvalidStructure {
22        /// Error message
23        message: String,
24    },
25
26    /// Source file not found
27    #[error("Source file not found: {path}")]
28    SourceNotFound {
29        /// Source file path
30        path: String,
31    },
32
33    /// Source file error
34    #[error("Source file error '{path}': {message}")]
35    SourceError {
36        /// Source file path
37        path: String,
38        /// Error message
39        message: String,
40    },
41
42    /// Invalid source configuration
43    #[error("Invalid source configuration: {message}")]
44    InvalidSource {
45        /// Error message
46        message: String,
47    },
48
49    /// Invalid band configuration
50    #[error("Invalid band configuration: {message}")]
51    InvalidBand {
52        /// Error message
53        message: String,
54    },
55
56    /// Band out of range
57    #[error("Band {band} out of range (0-{max})")]
58    BandOutOfRange {
59        /// Band index
60        band: usize,
61        /// Maximum band index
62        max: usize,
63    },
64
65    /// Invalid extent
66    #[error("Invalid extent: {message}")]
67    InvalidExtent {
68        /// Error message
69        message: String,
70    },
71
72    /// Invalid window
73    #[error("Invalid window: {message}")]
74    InvalidWindow {
75        /// Error message
76        message: String,
77    },
78
79    /// Invalid pixel function
80    #[error("Invalid pixel function: {function}")]
81    InvalidPixelFunction {
82        /// Function name
83        function: String,
84    },
85
86    /// Missing required attribute
87    #[error("Missing required attribute: {attribute}")]
88    MissingAttribute {
89        /// Attribute name
90        attribute: String,
91    },
92
93    /// Path resolution error
94    #[error("Path resolution error for '{path}': {message}")]
95    PathResolution {
96        /// Path that failed to resolve
97        path: String,
98        /// Error message
99        message: String,
100    },
101
102    /// Cache error
103    #[error("Cache error: {message}")]
104    CacheError {
105        /// Error message
106        message: String,
107    },
108
109    /// Incompatible sources
110    #[error("Incompatible sources: {message}")]
111    IncompatibleSources {
112        /// Error message
113        message: String,
114    },
115
116    /// I/O error
117    #[error("I/O error: {0}")]
118    Io(#[from] std::io::Error),
119
120    /// OxiGDAL core error
121    #[error("OxiGDAL error: {0}")]
122    Core(#[from] OxiGdalError),
123}
124
125impl VrtError {
126    /// Creates an XML parsing error
127    pub fn xml_parse<S: Into<String>>(message: S) -> Self {
128        Self::XmlParse {
129            message: message.into(),
130        }
131    }
132
133    /// Creates an invalid structure error
134    pub fn invalid_structure<S: Into<String>>(message: S) -> Self {
135        Self::InvalidStructure {
136            message: message.into(),
137        }
138    }
139
140    /// Creates a source not found error
141    pub fn source_not_found<S: Into<String>>(path: S) -> Self {
142        Self::SourceNotFound { path: path.into() }
143    }
144
145    /// Creates a source error
146    pub fn source_error<S: Into<String>, M: Into<String>>(path: S, message: M) -> Self {
147        Self::SourceError {
148            path: path.into(),
149            message: message.into(),
150        }
151    }
152
153    /// Creates an invalid source error
154    pub fn invalid_source<S: Into<String>>(message: S) -> Self {
155        Self::InvalidSource {
156            message: message.into(),
157        }
158    }
159
160    /// Creates an invalid band error
161    pub fn invalid_band<S: Into<String>>(message: S) -> Self {
162        Self::InvalidBand {
163            message: message.into(),
164        }
165    }
166
167    /// Creates a band out of range error
168    pub fn band_out_of_range(band: usize, max: usize) -> Self {
169        Self::BandOutOfRange { band, max }
170    }
171
172    /// Creates an invalid extent error
173    pub fn invalid_extent<S: Into<String>>(message: S) -> Self {
174        Self::InvalidExtent {
175            message: message.into(),
176        }
177    }
178
179    /// Creates an invalid window error
180    pub fn invalid_window<S: Into<String>>(message: S) -> Self {
181        Self::InvalidWindow {
182            message: message.into(),
183        }
184    }
185
186    /// Creates a missing attribute error
187    pub fn missing_attribute<S: Into<String>>(attribute: S) -> Self {
188        Self::MissingAttribute {
189            attribute: attribute.into(),
190        }
191    }
192
193    /// Creates a path resolution error
194    pub fn path_resolution<S: Into<String>, M: Into<String>>(path: S, message: M) -> Self {
195        Self::PathResolution {
196            path: path.into(),
197            message: message.into(),
198        }
199    }
200
201    /// Creates a cache error
202    pub fn cache_error<S: Into<String>>(message: S) -> Self {
203        Self::CacheError {
204            message: message.into(),
205        }
206    }
207
208    /// Creates an incompatible sources error
209    pub fn incompatible_sources<S: Into<String>>(message: S) -> Self {
210        Self::IncompatibleSources {
211            message: message.into(),
212        }
213    }
214}
215
216#[cfg(test)]
217mod tests {
218    use super::*;
219
220    #[test]
221    fn test_error_creation() {
222        let err = VrtError::xml_parse("test error");
223        assert!(matches!(err, VrtError::XmlParse { .. }));
224
225        let err = VrtError::source_not_found("/path/to/file.tif");
226        assert!(matches!(err, VrtError::SourceNotFound { .. }));
227
228        let err = VrtError::band_out_of_range(5, 3);
229        assert!(matches!(err, VrtError::BandOutOfRange { band: 5, max: 3 }));
230    }
231
232    #[test]
233    fn test_error_display() {
234        let err = VrtError::xml_parse("invalid XML");
235        assert_eq!(err.to_string(), "XML parsing error: invalid XML");
236
237        let err = VrtError::source_not_found("/test.tif");
238        assert_eq!(err.to_string(), "Source file not found: /test.tif");
239
240        let err = VrtError::band_out_of_range(5, 3);
241        assert_eq!(err.to_string(), "Band 5 out of range (0-3)");
242    }
243}