use oxigdal_core::error::OxiGdalError;
use thiserror::Error;
pub type Result<T> = core::result::Result<T, VrtError>;
#[derive(Debug, Error)]
pub enum VrtError {
#[error("XML parsing error: {message}")]
XmlParse {
message: String,
},
#[error("Invalid VRT structure: {message}")]
InvalidStructure {
message: String,
},
#[error("Source file not found: {path}")]
SourceNotFound {
path: String,
},
#[error("Source file error '{path}': {message}")]
SourceError {
path: String,
message: String,
},
#[error("Invalid source configuration: {message}")]
InvalidSource {
message: String,
},
#[error("Invalid band configuration: {message}")]
InvalidBand {
message: String,
},
#[error("Band {band} out of range (0-{max})")]
BandOutOfRange {
band: usize,
max: usize,
},
#[error("Invalid extent: {message}")]
InvalidExtent {
message: String,
},
#[error("Invalid window: {message}")]
InvalidWindow {
message: String,
},
#[error("Invalid pixel function: {function}")]
InvalidPixelFunction {
function: String,
},
#[error("Missing required attribute: {attribute}")]
MissingAttribute {
attribute: String,
},
#[error("Path resolution error for '{path}': {message}")]
PathResolution {
path: String,
message: String,
},
#[error("Cache error: {message}")]
CacheError {
message: String,
},
#[error("Incompatible sources: {message}")]
IncompatibleSources {
message: String,
},
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("OxiGDAL error: {0}")]
Core(#[from] OxiGdalError),
}
impl VrtError {
pub fn xml_parse<S: Into<String>>(message: S) -> Self {
Self::XmlParse {
message: message.into(),
}
}
pub fn invalid_structure<S: Into<String>>(message: S) -> Self {
Self::InvalidStructure {
message: message.into(),
}
}
pub fn source_not_found<S: Into<String>>(path: S) -> Self {
Self::SourceNotFound { path: path.into() }
}
pub fn source_error<S: Into<String>, M: Into<String>>(path: S, message: M) -> Self {
Self::SourceError {
path: path.into(),
message: message.into(),
}
}
pub fn invalid_source<S: Into<String>>(message: S) -> Self {
Self::InvalidSource {
message: message.into(),
}
}
pub fn invalid_band<S: Into<String>>(message: S) -> Self {
Self::InvalidBand {
message: message.into(),
}
}
pub fn band_out_of_range(band: usize, max: usize) -> Self {
Self::BandOutOfRange { band, max }
}
pub fn invalid_extent<S: Into<String>>(message: S) -> Self {
Self::InvalidExtent {
message: message.into(),
}
}
pub fn invalid_window<S: Into<String>>(message: S) -> Self {
Self::InvalidWindow {
message: message.into(),
}
}
pub fn missing_attribute<S: Into<String>>(attribute: S) -> Self {
Self::MissingAttribute {
attribute: attribute.into(),
}
}
pub fn path_resolution<S: Into<String>, M: Into<String>>(path: S, message: M) -> Self {
Self::PathResolution {
path: path.into(),
message: message.into(),
}
}
pub fn cache_error<S: Into<String>>(message: S) -> Self {
Self::CacheError {
message: message.into(),
}
}
pub fn incompatible_sources<S: Into<String>>(message: S) -> Self {
Self::IncompatibleSources {
message: message.into(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_creation() {
let err = VrtError::xml_parse("test error");
assert!(matches!(err, VrtError::XmlParse { .. }));
let err = VrtError::source_not_found("/path/to/file.tif");
assert!(matches!(err, VrtError::SourceNotFound { .. }));
let err = VrtError::band_out_of_range(5, 3);
assert!(matches!(err, VrtError::BandOutOfRange { band: 5, max: 3 }));
}
#[test]
fn test_error_display() {
let err = VrtError::xml_parse("invalid XML");
assert_eq!(err.to_string(), "XML parsing error: invalid XML");
let err = VrtError::source_not_found("/test.tif");
assert_eq!(err.to_string(), "Source file not found: /test.tif");
let err = VrtError::band_out_of_range(5, 3);
assert_eq!(err.to_string(), "Band 5 out of range (0-3)");
}
}