Skip to main content

Improve some of the error handling

ID
b5b2adf
date
2024-09-04 07:52:09+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
f4600ee
message
Improve some of the error handling
changed files
4 files, 67 additions, 28 deletions

Changed files

src/get_image_colors.rs (6156) → src/get_image_colors.rs (6976)

diff --git a/src/get_image_colors.rs b/src/get_image_colors.rs
index 2c8100c..5153ced 100644
--- a/src/get_image_colors.rs
+++ b/src/get_image_colors.rs
@@ -6,8 +6,9 @@
 //
 // It returns a Vec<Lab>, which can be passed to the k-means process.
 
+use std::fmt::Display;
 use std::fs::File;
-use std::io::{BufReader, Error, ErrorKind, Result};
+use std::io::BufReader;
 use std::path::PathBuf;
 
 use image::codecs::gif::GifDecoder;
@@ -17,38 +18,27 @@ use image::{AnimationDecoder, DynamicImage, Frame, ImageFormat};
 use palette::cast::from_component_slice;
 use palette::{IntoColor, Lab, Srgba};
 
-pub fn get_image_colors(path: &PathBuf) -> std::io::Result<Vec<Lab>> {
+pub fn get_image_colors(path: &PathBuf) -> Result<Vec<Lab>, GetImageColorsErr> {
     let format = get_format(path)?;
 
     let f = File::open(path)?;
     let reader = BufReader::new(f);
 
     let image_bytes = match format {
-        Some(ImageFormat::Gif) => {
-            let decoder = GifDecoder::new(reader).ok().unwrap();
+        ImageFormat::Gif => {
+            let decoder = GifDecoder::new(reader)?;
             get_bytes_for_animated_image(decoder)
         }
 
-        Some(ImageFormat::WebP) => {
-            let decoder = WebPDecoder::new(reader).ok().unwrap();
+        ImageFormat::WebP => {
+            let decoder = WebPDecoder::new(reader)?;
             get_bytes_for_animated_image(decoder)
         }
 
-        Some(format) => {
-            let decoder = match image::load(reader, format) {
-                Ok(im) => im,
-                Err(e) => {
-                    eprintln!("{}", e);
-                    std::process::exit(1)
-                }
-            };
+        format => {
+            let decoder = image::load(reader, format)?;
             get_bytes_for_static_image(decoder)
         }
-
-        _ => {
-            eprintln!("The image format could not be determined");
-            std::process::exit(1);
-        }
     };
 
     let lab: Vec<Lab> = from_component_slice::<Srgba<u8>>(&image_bytes)
@@ -59,13 +49,49 @@ pub fn get_image_colors(path: &PathBuf) -> std::io::Result<Vec<Lab>> {
     Ok(lab)
 }
 
-fn get_format(path: &PathBuf) -> Result<Option<ImageFormat>> {
-    match path.extension() {
+pub enum GetImageColorsErr {
+    IoError(std::io::Error),
+    ImageError(image::ImageError),
+    GetFormatError(String),
+}
+
+impl Display for GetImageColorsErr {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            GetImageColorsErr::IoError(io_error) =>
+                write!(f, "{}", io_error),
+            GetImageColorsErr::ImageError(image_error) =>
+                write!(f, "{}", image_error),
+            GetImageColorsErr::GetFormatError(format_error) =>
+                write!(f, "{}", format_error),
+        }
+    }
+}
+
+impl From<std::io::Error> for GetImageColorsErr {
+    fn from(e: std::io::Error) -> GetImageColorsErr {
+        return GetImageColorsErr::IoError(e)
+    }
+}
+
+impl From<image::ImageError> for GetImageColorsErr {
+    fn from(e: image::ImageError) -> GetImageColorsErr {
+        return GetImageColorsErr::ImageError(e)
+    }
+}
+
+fn get_format(path: &PathBuf) -> Result<ImageFormat, GetImageColorsErr> {
+    let format = match path.extension() {
         Some(ext) => Ok(image::ImageFormat::from_extension(ext)),
-        None => Err(Error::new(
-            ErrorKind::InvalidInput,
-            "Path has no file extension, so could not determine image format",
+        None => Err(GetImageColorsErr::GetFormatError(
+            "Path has no file extension, so could not determine image format".to_string()
         )),
+    };
+
+    match format {
+        Ok(Some(format)) => Ok(format),
+        Ok(None) => Err(GetImageColorsErr::GetFormatError("Unable to determine image format from file extension".to_string())),
+        Err(e) => Err(e),
     }
 }
 
@@ -163,11 +189,11 @@ mod test {
     // processed correctly.
     #[test]
     fn it_gets_colors_for_mri_fruit() {
-        get_image_colors(&PathBuf::from("./src/tests/garlic.gif")).unwrap();
+        assert!(get_image_colors(&PathBuf::from("./src/tests/garlic.gif")).is_ok());
     }
 
     #[test]
     fn get_colors_for_webp() {
-        get_image_colors(&PathBuf::from("./src/tests/purple.webp")).unwrap();
+        assert!(get_image_colors(&PathBuf::from("./src/tests/purple.webp")).is_ok());
     }
 }

src/main.rs (9423) → src/main.rs (9787)

diff --git a/src/main.rs b/src/main.rs
index 830e32d..98041af 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -222,7 +222,7 @@ mod tests {
 
         assert_eq!(output.exit_code, 1);
         assert_eq!(output.stdout, "");
-        assert_eq!(output.stderr, "The image format could not be determined\n");
+        assert_eq!(output.stderr, "Unable to determine image format from file extension\n");
     }
 
     #[test]
@@ -231,7 +231,7 @@ mod tests {
 
         assert_eq!(output.exit_code, 1);
         assert_eq!(output.stdout, "");
-        assert_eq!(output.stderr, "The image format could not be determined\n");
+        assert_eq!(output.stderr, "Unable to determine image format from file extension\n");
     }
 
     #[test]
@@ -247,6 +247,18 @@ mod tests {
     }
 
     #[test]
+    fn it_fails_if_you_pass_a_malformed_gif() {
+        let output = get_failure(&["./src/tests/malformed.txt.gif"]);
+
+        assert_eq!(output.exit_code, 1);
+        assert_eq!(output.stdout, "");
+        assert_eq!(
+            output.stderr,
+            "Format error decoding Gif: malformed GIF header\n"
+        );
+    }
+
+    #[test]
     fn it_fails_if_you_pass_a_path_without_a_file_extension() {
         let output = get_failure(&["./src/tests/noextension"]);
 

src/tests/malformed.txt.gif (0) → src/tests/malformed.txt.gif (22)

diff --git a/src/tests/malformed.txt.gif b/src/tests/malformed.txt.gif
new file mode 100644
index 0000000..d6d2570
--- /dev/null
+++ b/src/tests/malformed.txt.gif
@@ -0,0 +1 @@
+Ceci n'est pas une png
\ No newline at end of file

src/tests/noextension (0) → src/tests/noextension (0)

diff --git a/src/tests/noextension b/src/tests/noextension
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/tests/noextension