Add proper error handling and restructure code
Error handling using a custom error class was added. While adding error handling, the majority of the code was restructured.
This commit is contained in:
parent
ccd3d2c339
commit
84d6314e45
|
@ -168,18 +168,18 @@ checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.71"
|
||||
version = "1.0.74"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8"
|
||||
checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
@ -191,6 +191,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"clap",
|
||||
"rexiv2",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -212,15 +213,35 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.43"
|
||||
version = "2.0.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53"
|
||||
checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
|
|
|
@ -11,6 +11,7 @@ description = "Extract embedded thumbnail from raw image file"
|
|||
anyhow = "1.0.77"
|
||||
clap = { version = "4.4.12", features = ["derive"] }
|
||||
rexiv2 = "0.10.0"
|
||||
thiserror = "1.0.56"
|
||||
|
||||
[[bin]]
|
||||
name = "rex"
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum General {
|
||||
#[error("could not load metadata: {0}")]
|
||||
LoadMetadata(rexiv2::Rexiv2Error),
|
||||
#[error("not embedded thumbnail found")]
|
||||
NoThumbnail,
|
||||
#[error("could not store thumbnail: {0}")]
|
||||
StoreThumbnail(rexiv2::Rexiv2Error),
|
||||
#[error("could not get thumbnail extension: {0}")]
|
||||
GetExtension(rexiv2::Rexiv2Error),
|
||||
#[error("could not store metadata to thumbnail: {0}")]
|
||||
StoreMetadata(rexiv2::Rexiv2Error),
|
||||
}
|
111
src/main.rs
111
src/main.rs
|
@ -1,62 +1,79 @@
|
|||
#![feature(absolute_path)]
|
||||
pub mod commands;
|
||||
pub mod error;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use rexiv2::Metadata;
|
||||
use rexiv2::{Metadata, PreviewImage};
|
||||
|
||||
use commands::Cli;
|
||||
use error::General;
|
||||
|
||||
/// Get preview with largest resolution.
|
||||
fn get_largest_preview(metadata: &Metadata) -> Result<PreviewImage, General> {
|
||||
let previews: Vec<PreviewImage> = metadata.get_preview_images().ok_or(General::NoThumbnail)?;
|
||||
|
||||
let largest_preview: PreviewImage = previews
|
||||
.into_iter()
|
||||
.max_by_key(|e| e.get_size())
|
||||
.expect("previews is not supposed to be empty");
|
||||
|
||||
Ok(largest_preview)
|
||||
}
|
||||
|
||||
/// Extract thumbnail of `src` and store to `output_dir`.
|
||||
fn process_image(src: &PathBuf, output_dir: &Option<PathBuf>) -> Result<PathBuf, General> {
|
||||
assert!(src.is_absolute());
|
||||
let metadata = Metadata::new_from_path(src).map_err(|e| General::LoadMetadata(e))?;
|
||||
let preview = get_largest_preview(&metadata)?;
|
||||
|
||||
let mut dst = match output_dir {
|
||||
Some(e) => e.to_owned(),
|
||||
None => src
|
||||
.parent()
|
||||
.expect("image is supposed to have a parent")
|
||||
.to_owned(),
|
||||
};
|
||||
assert!(dst.is_dir());
|
||||
|
||||
// Set filename to name of source, without extension as `save_to_file` will add the appropriate extension
|
||||
dst.push(
|
||||
src.file_stem()
|
||||
.expect("image is supposed to have a filename"),
|
||||
);
|
||||
|
||||
preview
|
||||
.save_to_file(&dst)
|
||||
.map_err(|e| General::StoreThumbnail(e))?;
|
||||
|
||||
// Add correct extension
|
||||
dst.set_extension(
|
||||
preview
|
||||
.get_extension()
|
||||
.map_err(|e| General::GetExtension(e))?
|
||||
.strip_prefix(".")
|
||||
.expect("extension is supposed to start with ."),
|
||||
);
|
||||
assert!(dst.is_file());
|
||||
|
||||
metadata
|
||||
.save_to_file(&dst)
|
||||
.map_err(|e| General::StoreMetadata(e))?;
|
||||
|
||||
Ok(dst)
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
for src in cli.input_images.iter() {
|
||||
assert!(src.is_absolute());
|
||||
|
||||
println!("Processing image {:?}", src);
|
||||
let metadata = Metadata::new_from_path(&src)?;
|
||||
|
||||
if let Some(previews) = metadata.get_preview_images() {
|
||||
// Get preview with highest resolution
|
||||
let preview = previews
|
||||
.iter()
|
||||
.max_by_key(|e| e.get_size())
|
||||
.expect("previews is not supposed to be empty");
|
||||
|
||||
let mut dst = match cli.output_dir {
|
||||
Some(ref e) => e.to_owned(),
|
||||
None => src
|
||||
.parent()
|
||||
.expect("image is supposed to have a parent")
|
||||
.to_owned(),
|
||||
};
|
||||
assert!(dst.is_dir());
|
||||
|
||||
// Set filename to name of source, without extension as `save_to_file` will add the appropriate extension
|
||||
dst.push(
|
||||
src.file_stem()
|
||||
.expect("image is supposed to have a filename"),
|
||||
);
|
||||
|
||||
preview
|
||||
.save_to_file(&dst)
|
||||
.expect("failed to save preview to file");
|
||||
|
||||
dst.set_extension(
|
||||
preview
|
||||
.get_extension()
|
||||
.expect("failed to get preview extension")
|
||||
.strip_prefix(".")
|
||||
.expect("extension is supposed to start with ."),
|
||||
);
|
||||
assert!(dst.is_file());
|
||||
|
||||
metadata
|
||||
.save_to_file(&dst)
|
||||
.expect("failed to save metadata to file");
|
||||
println!("Stored preview to {:?}", dst);
|
||||
} else {
|
||||
println!("Image {:?} contains no embedded JPG", src);
|
||||
match process_image(src, &cli.output_dir) {
|
||||
Ok(dst) => println!("Stored thumbnail to {:?}", dst),
|
||||
Err(e) => {
|
||||
println!("Error while processing image {:?}: {}", src, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue