Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve error handling #1

Merged
merged 3 commits into from
Sep 7, 2024
Merged

Conversation

y-mx-b
Copy link
Contributor

@y-mx-b y-mx-b commented Sep 6, 2024

Remove usage of anyhow in library code, improve ImageLoaderError instead.

Cleaned up some of the image loading code and made the API a little more flexible.

Removed usages of find_images within load_images. Ideally, one should call find_images before using load_images once instead, and then load all the resulting images.

@y-mx-b
Copy link
Contributor Author

y-mx-b commented Sep 6, 2024

The devcontainer.json is there because I need it to write code and I was too lazy to remove it from the git history before making this pull request.

Edit: Now removed

}

/// Finds all `.jpg`, `.jpeg`, `.png` and `.webp` images within a directory.
///
/// Throws an error if:
/// - The directory is invalid or does not contain any images.
/// - The directory does not contain any jpg, jpeg, png, or webp images.
pub fn find_images(directory_path: &str) -> anyhow::Result<Vec<PathBuf>> {
let mut images: Vec<_> = read_dir(directory_path)?
pub fn find_images(directory_path: impl AsRef<Path>) -> Result<Vec<PathBuf>, ImageLoaderError> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed this function to accept a generic parameter to make it more flexible. This means you can, for instance, provide a &PathBuf instead of a &str (useful for application code).

Note that there is a compile-time cost due to monomorphization, but if that becomes a problem, I can fix it with the non-generic inner function hack

let mut images: Vec<_> = read_dir(directory_path)?
pub fn find_images(directory_path: impl AsRef<Path>) -> Result<Vec<PathBuf>, ImageLoaderError> {
// create pathbuf, check if path is a directory
let path = PathBuf::from(directory_path.as_ref());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check if a path is a directory from the metadata before operating on it. IO errors kinda suck in Rust's standard library, so it's easier to handle non-directory paths like this than attempt to use io::Error (additional ErrorKinds are a work-in-progress).


// get images
let mut images: Vec<_> = read_dir(directory_path)
.map_err(|e| ImageLoaderError::from_io_error(e, path))?
Copy link
Contributor Author

@y-mx-b y-mx-b Sep 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the map_err usage is required because ImageLoaderError holds additional context (the path in question) that io::Error doesn't provide, so a From<io::Error> implementation isn't possible.

});

// sort images by natural order
images.sort_by(|a, b| natord::compare(&a.display().to_string(), &b.display().to_string()));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Favor .display().to_string() over .file_name().unwrap().to_str().unwrap(). If there are non-textual bytes in the file name, then we should just try to gloss over it as best as possible instead of crashing the program.

let dimensions = find_images(directory_path)?
.into_iter()
.map(|image| image_dimensions(image).map_err(|e| ImageLoaderError::from(e)))
pub fn load_images(paths: &[impl AsRef<Path>], width: Option<u32>) -> Result<RgbImage, ImageLoaderError> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion, load_images should just load a given set of images, and find_images should be used instead to find the images to load.

@@ -17,16 +17,16 @@ use thiserror::Error;
/// Errors related to loading images.
pub enum ImageLoaderError {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed usage of PathBuf here because I figured it's usually unnecessary to also provide the path. If necessary in the future, we can add an Option<PathBuf> instead.

Removing PathBuf in the error also allows for a From<io::Error> implementation.

match err.kind() {
Kind::NotFound => ImageLoaderError::NotFound(path),
Kind::PermissionDenied => ImageLoaderError::PermissionDenied(path),
impl From<io::Error> for ImageLoaderError {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a From<io::Error> implementation for simpler error handling, replacing the prior from_io_error function. You can just use ? to bubble up IO errors now.

@y-mx-b
Copy link
Contributor Author

y-mx-b commented Sep 7, 2024

Also note that I ran cargo format, so that may have made changes to other files, I didn't bother to check for that. If it did, would be a you problem, image not running cargo format.

@y-mx-b y-mx-b mentioned this pull request Sep 7, 2024
6 tasks
@y-mx-b y-mx-b force-pushed the improve-error-handling branch from dd0ddc5 to edff0a2 Compare September 7, 2024 09:19
@y-mx-b
Copy link
Contributor Author

y-mx-b commented Sep 7, 2024

Removed dev container config from git history.

@quietkiro quietkiro merged commit c70dd1a into quietkiro:main Sep 7, 2024
@y-mx-b y-mx-b deleted the improve-error-handling branch October 23, 2024 12:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants