From c47edd2ffaa36347d12703e13c5066fbdcdc2675 Mon Sep 17 00:00:00 2001 From: Julia Naomi Date: Fri, 9 Oct 2020 01:26:13 -0300 Subject: [PATCH] generates qrcode files and string --- Cargo.toml | 3 ++- README.md | 19 +++++++++++++++++-- src/lib.rs | 41 ++++++++++++++++++++++++++++++++++++++--- src/model.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2945c51..e7b399e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "brcode" -version = "1.3.1" +version = "1.4.0" authors = ["Julia Naomi "] edition = "2018" description = "Crate to parse and emit BR Codes" @@ -23,6 +23,7 @@ edn-derive = "0.4.2" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" serde_derive = "1" +qrcode-generator = "4.0.3" [dev-dependencies] criterion = "0.3" diff --git a/README.md b/README.md index 46e4113..72c41c1 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ A crate to parse and emit [PIX BR Code](https://www.bcb.gov.br/content/estabilid ```toml [dependencies] -brcode = "1.3.1" +brcode = "1.4.0" ``` ### Build from source @@ -282,12 +282,27 @@ fn brcode_value() -> BrCode { } ``` -**`BrCode` functions** +**`BrCode` functions** context related * `pub fn is_pix(&self) -> bool` determines if BrCode is a `PIX` transaction. * `pub fn get_transaction_id(&self) -> Option` gets `transaction_id` value (field 5 of item 65). * `pub fn get_alias(&self) -> Option>` gets all possible values for PIX aliases. Usually only field 1 of item 26 is valid. Checks if the alias if of type `"BR.GOV.BCB.PIX"`. * `pub fn get_message(&self) -> Option>` gets all possible massages for PIX aliases. Usually only field 2 of item 26 is valid. Checks if the alias if of type `"BR.GOV.BCB.PIX"`. +**`BrCode` functions** QrCode generation related: +* `to_svg_string(&self, ecc: QrCodeEcc, size: usize) -> String` generates a SVG xml in a String. +* `to_svg_standard_string(&self) -> String` generates a SVG xml in a String with `QrCodeEcc::Low` and `size = 1024`. +* `to_vec_u8(&self, ecc: QrCodeEcc, size: usize) -> Vec` generates a PNG formatted in `Vec`. +* `to_svg_file(&self, file_path: &str, ecc: QrCodeEcc, size: usize)` creates a QR Code in format `.svg` located at file path `file_path`. +* `to_standard_svg_file(&self, file_path: &str)` creates a QR Code in format `.svg` located at file path `file_path` with `QrCodeEcc::Low` and `size = 1024`. +* `to_png_file(&self, file_path: &str, ecc: QrCodeEcc, size: usize)` creates a QR Code in format `.png` located at file path `file_path`. + +* `file_path` examples are `tests/data/file_output.png` and `tests/data/file_output.svg` from the project root. If directory doesn't exist an error will be thrown. +* `QrCodeEcc` is the error correction level in a QR Code symbol and `size` is the image size. + * `QrCodeEcc::Low` The QR Code can tolerate about 7% erroneous codewords. + * `QrCodeEcc::Medium` The QR Code can tolerate about 15% erroneous codewords. + * `QrCodeEcc::Quartile` The QR Code can tolerate about 25% erroneous codewords. + * `QrCodeEcc::High` The QR Code can tolerate about 30% erroneous codewords. + ## Benchmark **from_str** in `benches/parse.rs` diff --git a/src/lib.rs b/src/lib.rs index 50c79c1..e72dd6f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ pub(crate) mod parse; pub use aux::crc16_ccitt; pub use model::{BrCode, Info, Label, MerchantInfo, Template}; pub use parse::Data; +pub use qrcode_generator::QrCodeEcc; pub fn from_str(code: &str) -> Vec<(usize, parse::Data)> { parse::parse(code, 99) @@ -65,6 +66,23 @@ pub extern "C" fn edn_to_brcode(edn: *const c_char) -> *const c_char { to_c_char(&brcode_to_string(brcode)) } +#[no_mangle] +pub extern "C" fn edn_to_svg_brcode(edn: *const c_char) -> *const c_char { + let edn_str = chars_to_string(edn); + let brcode: BrCode = edn_rs::from_str(&edn_str).unwrap(); + let svg = brcode.to_svg_standard_string(); + + to_c_char(&svg) +} + +#[no_mangle] +pub extern "C" fn edn_to_svg_file(edn: *const c_char, file_path: *const c_char) { + let edn_str = chars_to_string(edn); + let file_path_str = chars_to_string(file_path); + let brcode: BrCode = edn_rs::from_str(&edn_str).unwrap(); + brcode.to_standard_svg_file(&file_path_str); +} + // Json #[no_mangle] pub extern "C" fn json_from_brcode(json: *const c_char) -> *const c_char { @@ -74,9 +92,26 @@ pub extern "C" fn json_from_brcode(json: *const c_char) -> *const c_char { } #[no_mangle] -pub extern "C" fn json_to_brcode(edn: *const c_char) -> *const c_char { - let edn_str = chars_to_string(edn); - let brcode: BrCode = serde_json::from_str(&edn_str).unwrap(); +pub extern "C" fn json_to_brcode(json: *const c_char) -> *const c_char { + let json_str = chars_to_string(json); + let brcode: BrCode = serde_json::from_str(&json_str).unwrap(); to_c_char(&brcode_to_string(brcode)) } + +#[no_mangle] +pub extern "C" fn json_to_svg_brcode(json: *const c_char) -> *const c_char { + let json_str = chars_to_string(json); + let brcode: BrCode = serde_json::from_str(&json_str).unwrap(); + let svg = brcode.to_svg_standard_string(); + + to_c_char(&svg) +} + +#[no_mangle] +pub extern "C" fn json_to_svg_file(json: *const c_char, file_path: *const c_char) { + let json_str = chars_to_string(json); + let file_path_str = chars_to_string(file_path); + let brcode: BrCode = serde_json::from_str(&json_str).unwrap(); + brcode.to_standard_svg_file(&file_path_str); +} \ No newline at end of file diff --git a/src/model.rs b/src/model.rs index def18c9..51e74b2 100644 --- a/src/model.rs +++ b/src/model.rs @@ -2,6 +2,7 @@ use crate::aux::HashBrCode; use crate::parse::Data; use edn_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize}; +use qrcode_generator::QrCodeEcc; #[derive(Debug, PartialEq, Clone, Serialize, Deserialize, SerdeDeserialize, SerdeSerialize)] pub struct BrCode { @@ -272,6 +273,39 @@ impl BrCode { encode.push_str(&crc16); encode } + + pub fn to_svg_string(&self, ecc: QrCodeEcc, size: usize) -> String { + let brcode = self.clone().encode(); + let result: String = qrcode_generator::to_svg_to_string(&brcode.clone(), ecc, size, Some(brcode)).unwrap(); + result + } + + pub fn to_svg_standard_string(&self) -> String { + let brcode = self.clone().encode(); + let result: String = qrcode_generator::to_svg_to_string(&brcode.clone(), QrCodeEcc::Low, 1024, Some(brcode)).unwrap(); + result + } + + pub fn to_vec_u8(&self, ecc: QrCodeEcc, size: usize) -> Vec { + let brcode = self.clone().encode(); + let result = qrcode_generator::to_png_to_vec(&brcode, ecc, size).unwrap(); + result + } + + pub fn to_svg_file(&self, file_path: &str, ecc: QrCodeEcc, size: usize) { + let brcode = self.clone().encode(); + qrcode_generator::to_svg_to_file(&brcode.clone(), ecc, size, Some(brcode), file_path).unwrap(); + } + + pub fn to_standard_svg_file(&self, file_path: &str) { + let brcode = self.clone().encode(); + qrcode_generator::to_svg_to_file(&brcode.clone(), QrCodeEcc::Low, 1024, Some(brcode), file_path).unwrap(); + } + + pub fn to_png_file(&self, file_path: &str, ecc: QrCodeEcc, size: usize) { + let brcode = self.clone().encode(); + qrcode_generator::to_png_to_file(&brcode.clone(), ecc, size, file_path).unwrap(); + } } #[cfg(test)] @@ -291,6 +325,12 @@ mod test { assert_eq!(actual, expected); } + #[test] + fn brcode_to_svg() { + let svg = expected().to_svg_standard_string(); + assert_eq!(&svg[38..42], " BrCode { BrCode { payload_version: 1,