use std::path::PathBuf;
#[derive(Debug, thiserror::Error)]
pub enum ImageError {
#[error("couldn't read {path}: {source}")]
Unreadable {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("{path} isn't an image this build can decode: {source}")]
Undecodable {
path: PathBuf,
#[source]
source: image::ImageError,
},
#[error("{path} is {width}x{height}, which is too large to decode safely")]
TooLarge { path: PathBuf, width: u32, height: u32 },
}
impl ImageError {
pub fn path(&self) -> &std::path::Path {
match self {
ImageError::Unreadable { path, .. }
| ImageError::Undecodable { path, .. }
| ImageError::TooLarge { path, .. } => path,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::ErrorKind;
#[test]
fn a_missing_file_and_an_unsupported_one_do_not_say_the_same_thing() {
let missing = ImageError::Unreadable {
path: PathBuf::from("/x/gone.png"),
source: std::io::Error::new(ErrorKind::NotFound, "no such file"),
};
let unsupported = ImageError::TooLarge {
path: PathBuf::from("/x/huge.png"),
width: 200_000,
height: 4,
};
assert_ne!(missing.to_string(), unsupported.to_string());
assert!(missing.to_string().contains("gone.png"));
assert!(unsupported.to_string().contains("200000"));
}
#[test]
fn every_failure_names_the_file_it_is_about() {
let e = ImageError::Unreadable {
path: PathBuf::from("/photos/a.jpg"),
source: std::io::Error::new(ErrorKind::PermissionDenied, "denied"),
};
assert_eq!(e.path(), std::path::Path::new("/photos/a.jpg"));
assert!(e.to_string().contains("/photos/a.jpg"));
}
}