Skip to content

Commit

Permalink
refactor: cleanup code
Browse files Browse the repository at this point in the history
  • Loading branch information
mike committed Oct 24, 2024
1 parent 25926a7 commit abc2337
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 53 deletions.
59 changes: 33 additions & 26 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -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.
//!
Expand All @@ -9,49 +9,56 @@ 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<QRData> {
let tmp_dir = tempdir().expect("Error creating temporary directory");
pub fn get_qr_bill_data(file_path: &str, fail_on_error: bool) -> Vec<QRData> {
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<DynamicImage> {
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<Result<QRData, String>> {
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::<Vec<_>>()
})
.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<QRData, String>], 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);
}
}

std::process::exit(1);
}

all_qr_codes.into_iter().flatten().collect()
}
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
40 changes: 20 additions & 20 deletions tests/edge_cases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ 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());
}

#[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());
}

#[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());
Expand All @@ -29,31 +29,31 @@ 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());
}

#[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());
}

#[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());
}

#[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());
Expand All @@ -62,31 +62,31 @@ 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());
}

#[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());
}

#[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());
}

#[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());
Expand All @@ -95,15 +95,15 @@ 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());
}

#[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()];

Expand All @@ -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()];

Expand All @@ -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()];

Expand All @@ -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());
Expand All @@ -147,29 +147,29 @@ 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());
}

#[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());
}
Expand Down
12 changes: 6 additions & 6 deletions tests/six_examples.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand All @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down

0 comments on commit abc2337

Please sign in to comment.