From abc2337304ac38d774cfff651741d2dd173c7ca9 Mon Sep 17 00:00:00 2001 From: mike Date: Thu, 24 Oct 2024 12:53:58 +0200 Subject: [PATCH] refactor: cleanup code --- src/lib.rs | 59 ++++++++++++++++++++++++------------------- src/main.rs | 2 +- tests/edge_cases.rs | 40 ++++++++++++++--------------- tests/six_examples.rs | 12 ++++----- 4 files changed, 60 insertions(+), 53 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 758f7f7..014b380 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -//! # Simple program to read swiss invoices QR codes as pdf or png files and the relevant data +//! # Simple program to read Swiss invoice QR codes from PDF or PNG files and extract relevant data //! //! This program reads QR codes from Swiss invoices and outputs the relevant data as JSON. //! @@ -9,42 +9,51 @@ mod pdf_converter; mod qr_parser; use crate::models::qr_data::QRData; +use image::DynamicImage; use rayon::prelude::*; use rqrr::PreparedImage; +use std::path::Path; use tempfile::tempdir; -pub fn get_qr_bill_data(file_path: String, fail_on_error: bool) -> Vec { - let tmp_dir = tempdir().expect("Error creating temporary directory"); +pub fn get_qr_bill_data(file_path: &str, fail_on_error: bool) -> Vec { + let tmp_dir = tempdir().expect("Failed to create temporary directory"); - let images = match file_path.to_lowercase().as_str() { - input if input.ends_with(".pdf") => { - pdf_converter::convert_to_png(&file_path, tmp_dir.path()) - } + let images = load_images(file_path, tmp_dir.path()); + + let qr_data_results: Vec<_> = images + .into_par_iter() + .flat_map(|img| extract_qr_data(&img)) + .collect(); + + handle_errors(&qr_data_results, fail_on_error); + + qr_data_results.into_iter().filter_map(Result::ok).collect() +} + +fn load_images(file_path: &str, tmp_dir_path: &Path) -> Vec { + match file_path.to_lowercase().as_str() { + input if input.ends_with(".pdf") => pdf_converter::convert_to_png(file_path, tmp_dir_path), input if input.ends_with(".png") || input.ends_with(".jpg") || input.ends_with(".jpeg") => { - vec![image::open(&file_path).expect("Error loading image")] + vec![image::open(file_path).expect("Failed to load image")] } _ => panic!("Unsupported file format"), - }; + } +} - let all_qr_codes: Vec<_> = images +fn extract_qr_data(img: &DynamicImage) -> Vec> { + PreparedImage::prepare(img.to_luma8()) + .detect_grids() .into_par_iter() - .map(|img| { - let mut img = PreparedImage::prepare(img.to_luma8()); - img.detect_grids() - .into_par_iter() - .filter_map(|result| result.decode().ok()) - .map(|(_, content)| qr_parser::get_qr_code_data(&content)) - .collect::>() - }) - .flatten() - .collect(); + .filter_map(|grid| grid.decode().ok()) + .map(|(_, content)| qr_parser::get_qr_code_data(&content)) + .collect() +} - // check if there were any errors - if fail_on_error && all_qr_codes.iter().any(|result| result.is_err()) { +fn handle_errors(results: &[Result], fail_on_error: bool) { + if fail_on_error && results.iter().any(Result::is_err) { eprintln!("Error parsing QR codes"); - // print the errors - for result in all_qr_codes { + for result in results { if let Err(err) = result { eprintln!("{}", err); } @@ -52,6 +61,4 @@ pub fn get_qr_bill_data(file_path: String, fail_on_error: bool) -> Vec { std::process::exit(1); } - - all_qr_codes.into_iter().flatten().collect() } diff --git a/src/main.rs b/src/main.rs index 6cb76fe..f745496 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ use swiss_qr_bill_decoder::get_qr_bill_data; fn main() { let args = args::Args::parse(); - let all_qr_codes: Vec<_> = get_qr_bill_data(args.input, args.fail_on_error); + let all_qr_codes: Vec<_> = get_qr_bill_data(args.input.as_ref(), args.fail_on_error); // Serialize QR code data to stdout let writer = if args.pretty { diff --git a/tests/edge_cases.rs b/tests/edge_cases.rs index 85924cb..58a8777 100644 --- a/tests/edge_cases.rs +++ b/tests/edge_cases.rs @@ -4,7 +4,7 @@ use swiss_qr_bill_decoder::models::qr_data::QRData; #[test] fn minimal_png() { - let actual = get_qr_bill_data("tests/data/minimal.png".to_string(), true); + let actual = get_qr_bill_data("tests/data/minimal.png", true); assert_eq!(actual.len(), 1); assert_eq!(actual[0], expected_minimal()); @@ -12,7 +12,7 @@ fn minimal_png() { #[test] fn minimal_jpg() { - let actual = get_qr_bill_data("tests/data/minimal.jpg".to_string(), true); + let actual = get_qr_bill_data("tests/data/minimal.jpg", true); assert_eq!(actual.len(), 1); assert_eq!(actual[0], expected_minimal()); @@ -20,7 +20,7 @@ fn minimal_jpg() { #[test] fn minimal_jpeg() { - let actual = get_qr_bill_data("tests/data/minimal.jpeg".to_string(), true); + let actual = get_qr_bill_data("tests/data/minimal.jpeg", true); assert_eq!(actual.len(), 1); assert_eq!(actual[0], expected_minimal()); @@ -29,7 +29,7 @@ fn minimal_jpeg() { #[test] #[ignore] fn minimal_pdf() { - let actual = get_qr_bill_data("tests/data/minimal.pdf".to_string(), true); + let actual = get_qr_bill_data("tests/data/minimal.pdf", true); assert_eq!(actual.len(), 1); assert_eq!(actual[0], expected_minimal()); @@ -37,7 +37,7 @@ fn minimal_pdf() { #[test] fn full_png() { - let actual = get_qr_bill_data("tests/data/full.png".to_string(), true); + let actual = get_qr_bill_data("tests/data/full.png", true); assert_eq!(actual.len(), 1); assert_eq!(actual[0], expected_full()); @@ -45,7 +45,7 @@ fn full_png() { #[test] fn full_jpg() { - let actual = get_qr_bill_data("tests/data/full.jpg".to_string(), true); + let actual = get_qr_bill_data("tests/data/full.jpg", true); assert_eq!(actual.len(), 1); assert_eq!(actual[0], expected_full()); @@ -53,7 +53,7 @@ fn full_jpg() { #[test] fn full_jpeg() { - let actual = get_qr_bill_data("tests/data/full.jpeg".to_string(), true); + let actual = get_qr_bill_data("tests/data/full.jpeg", true); assert_eq!(actual.len(), 1); assert_eq!(actual[0], expected_full()); @@ -62,7 +62,7 @@ fn full_jpeg() { #[test] #[ignore] fn full_pdf() { - let actual = get_qr_bill_data("tests/data/full.pdf".to_string(), true); + let actual = get_qr_bill_data("tests/data/full.pdf", true); assert_eq!(actual.len(), 1); assert_eq!(actual[0], expected_full()); @@ -70,7 +70,7 @@ fn full_pdf() { #[test] fn rotated_png() { - let actual = get_qr_bill_data("tests/data/rotated.png".to_string(), true); + let actual = get_qr_bill_data("tests/data/rotated.png", true); assert_eq!(actual.len(), 1); assert_eq!(actual[0], expected_rotated()); @@ -78,7 +78,7 @@ fn rotated_png() { #[test] fn rotated_jpg() { - let actual = get_qr_bill_data("tests/data/rotated.jpg".to_string(), true); + let actual = get_qr_bill_data("tests/data/rotated.jpg", true); assert_eq!(actual.len(), 1); assert_eq!(actual[0], expected_rotated()); @@ -86,7 +86,7 @@ fn rotated_jpg() { #[test] fn rotated_jpeg() { - let actual = get_qr_bill_data("tests/data/rotated.jpeg".to_string(), true); + let actual = get_qr_bill_data("tests/data/rotated.jpeg", true); assert_eq!(actual.len(), 1); assert_eq!(actual[0], expected_rotated()); @@ -95,7 +95,7 @@ fn rotated_jpeg() { #[test] #[ignore] fn rotated_pdf() { - let actual = get_qr_bill_data("tests/data/rotated.pdf".to_string(), true); + let actual = get_qr_bill_data("tests/data/rotated.pdf", true); assert_eq!(actual.len(), 1); assert_eq!(actual[0], expected_rotated()); @@ -103,7 +103,7 @@ fn rotated_pdf() { #[test] fn double_png() { - let actual = get_qr_bill_data("tests/data/double.png".to_string(), true); + let actual = get_qr_bill_data("tests/data/double.png", true); let expected = vec![expected_double_1(), expected_double_2()]; @@ -114,7 +114,7 @@ fn double_png() { #[test] fn double_jpg() { - let actual = get_qr_bill_data("tests/data/double.jpg".to_string(), true); + let actual = get_qr_bill_data("tests/data/double.jpg", true); let expected = vec![expected_double_1(), expected_double_2()]; @@ -125,7 +125,7 @@ fn double_jpg() { #[test] fn double_jpeg() { - let actual = get_qr_bill_data("tests/data/double.jpeg".to_string(), true); + let actual = get_qr_bill_data("tests/data/double.jpeg", true); let expected = vec![expected_double_1(), expected_double_2()]; @@ -137,7 +137,7 @@ fn double_jpeg() { #[test] #[ignore] fn double_pdf() { - let actual = get_qr_bill_data("tests/data/double.pdf".to_string(), true); + let actual = get_qr_bill_data("tests/data/double.pdf", true); let expected = vec![expected_double_1(), expected_double_2()]; assert_eq!(actual.len(), expected.len()); @@ -147,21 +147,21 @@ fn double_pdf() { #[test] fn none_png() { - let actual = get_qr_bill_data("tests/data/none.png".to_string(), true); + let actual = get_qr_bill_data("tests/data/none.png", true); assert!(actual.is_empty()); } #[test] fn none_jpg() { - let actual = get_qr_bill_data("tests/data/none.jpg".to_string(), true); + let actual = get_qr_bill_data("tests/data/none.jpg", true); assert!(actual.is_empty()); } #[test] fn none_jpeg() { - let actual = get_qr_bill_data("tests/data/none.jpeg".to_string(), true); + let actual = get_qr_bill_data("tests/data/none.jpeg", true); assert!(actual.is_empty()); } @@ -169,7 +169,7 @@ fn none_jpeg() { #[test] #[ignore] fn none_pdf() { - let actual = get_qr_bill_data("tests/data/none.pdf".to_string(), true); + let actual = get_qr_bill_data("tests/data/none.pdf", true); assert!(actual.is_empty()); } diff --git a/tests/six_examples.rs b/tests/six_examples.rs index da6d007..ded0a64 100644 --- a/tests/six_examples.rs +++ b/tests/six_examples.rs @@ -4,7 +4,7 @@ use swiss_qr_bill_decoder::models::qr_data::QRData; #[test] fn six_example_01() { - let actual = get_qr_bill_data("tests/data/six_examples/01.png".to_string(), true); + let actual = get_qr_bill_data("tests/data/six_examples/01.png", true); let expected = vec![QRData::new( "CH6431961000004421557".to_string(), @@ -35,7 +35,7 @@ fn six_example_01() { #[test] fn six_example_02() { - let actual = get_qr_bill_data("tests/data/six_examples/02.png".to_string(), true); + let actual = get_qr_bill_data("tests/data/six_examples/02.png", true); let expected = vec![QRData::new( "CH4431999123000889012".to_string(), @@ -66,7 +66,7 @@ fn six_example_02() { #[test] fn six_example_03() { - let actual = get_qr_bill_data("tests/data/six_examples/03.png".to_string(), true); + let actual = get_qr_bill_data("tests/data/six_examples/03.png", true); let expected = vec![QRData::new( "CH5204835012345671000".to_string(), @@ -91,7 +91,7 @@ fn six_example_03() { #[test] fn six_example_04() { - let actual = get_qr_bill_data("tests/data/six_examples/04.png".to_string(), true); + let actual = get_qr_bill_data("tests/data/six_examples/04.png", true); let expected = vec![QRData::new( "CH5800791123000889012".to_string(), @@ -122,7 +122,7 @@ fn six_example_04() { #[test] fn six_example_05() { - let actual = get_qr_bill_data("tests/data/six_examples/05.png".to_string(), true); + let actual = get_qr_bill_data("tests/data/six_examples/05.png", true); let expected = vec![QRData::new( "CH5800791123000889012".to_string(), @@ -153,7 +153,7 @@ fn six_example_05() { #[test] fn six_example_06() { - let actual = get_qr_bill_data("tests/data/six_examples/06.png".to_string(), true); + let actual = get_qr_bill_data("tests/data/six_examples/06.png", true); let expected = vec![QRData::new( "CH5800791123000889012".to_string(),