crapify 0.3.0

Deep-fry your images, and other crimes against pixels.
use std::path::Path;

use image::{DynamicImage, ImageFormat, ImageReader};

use crate::error::CrapifyError;

pub fn decode_input(path: &Path) -> Result<DynamicImage, CrapifyError> {
    if !path.exists() {
        return Err(CrapifyError::MissingInput(path.to_path_buf()));
    }
    if path.is_dir() {
        return Err(CrapifyError::InputIsDirectory(path.to_path_buf()));
    }
    ImageReader::open(path)?
        .with_guessed_format()?
        .decode()
        .map_err(CrapifyError::DecoderError)
}

pub fn encode_output(
    img: &DynamicImage,
    path: &Path,
    fmt: ImageFormat,
) -> Result<(), CrapifyError> {
    img.save_with_format(path, fmt)
        .map_err(CrapifyError::EncoderError)
}

pub fn output_format(path: &Path, fmt_override: Option<&str>) -> Result<ImageFormat, CrapifyError> {
    let ext = match fmt_override {
        Some(s) => s,
        None => path.extension().and_then(|e| e.to_str()).unwrap_or(""),
    };
    ImageFormat::from_extension(ext).ok_or_else(|| CrapifyError::UnsupportedFormat(ext.to_string()))
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::path::PathBuf;

    #[test]
    fn output_format_infers_png() {
        let fmt = output_format(&PathBuf::from("out.png"), None).unwrap();
        assert_eq!(fmt, ImageFormat::Png);
    }

    #[test]
    fn output_format_infers_jpeg() {
        let fmt = output_format(&PathBuf::from("out.jpg"), None).unwrap();
        assert_eq!(fmt, ImageFormat::Jpeg);
    }

    #[test]
    fn output_format_override_wins() {
        let fmt = output_format(&PathBuf::from("out.bin"), Some("jpg")).unwrap();
        assert_eq!(fmt, ImageFormat::Jpeg);
    }

    #[test]
    fn output_format_unknown_extension_errors() {
        let err = output_format(&PathBuf::from("out.xyz"), None).unwrap_err();
        match err {
            CrapifyError::UnsupportedFormat(s) => assert_eq!(s, "xyz"),
            _ => panic!("expected UnsupportedFormat"),
        }
    }

    #[test]
    fn output_format_unknown_override_errors() {
        let err = output_format(&PathBuf::from("out.png"), Some("nope")).unwrap_err();
        match err {
            CrapifyError::UnsupportedFormat(s) => assert_eq!(s, "nope"),
            _ => panic!("expected UnsupportedFormat"),
        }
    }
}